spree_core 4.10.1 → 5.0.0.rc1

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 (476) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/spree_core_manifest.js +4 -0
  3. data/app/assets/images/google_on_white_hdpi.png +0 -0
  4. data/app/controllers/spree/base_controller.rb +1 -4
  5. data/app/finders/spree/orders/find_complete.rb +14 -2
  6. data/app/finders/spree/products/find.rb +74 -23
  7. data/app/finders/spree/stores/find_current.rb +6 -2
  8. data/app/helpers/spree/addresses_helper.rb +106 -0
  9. data/app/helpers/spree/base_helper.rb +83 -55
  10. data/app/helpers/spree/currency_helper.rb +12 -0
  11. data/app/helpers/spree/images_helper.rb +18 -0
  12. data/app/helpers/spree/mail_helper.rb +24 -0
  13. data/app/helpers/spree/products_helper.rb +1 -20
  14. data/app/javascript/spree/core/controllers/address_autocomplete_controller.js +233 -0
  15. data/app/javascript/spree/core/controllers/address_form_controller.js +98 -0
  16. data/app/javascript/spree/core/controllers/enable_button_controller.js +29 -0
  17. data/app/javascript/spree/core/helpers/address_autocomplete/google_places_suggestions_provider.js +179 -0
  18. data/app/javascript/spree/core/helpers/debounce.js +9 -0
  19. data/app/javascript/spree/core/helpers/scroll_lock.js +25 -0
  20. data/app/jobs/spree/addresses/geocode_address_job.rb +31 -0
  21. data/app/jobs/spree/base_job.rb +1 -0
  22. data/app/jobs/spree/coupon_codes/bulk_generate_job.rb +17 -0
  23. data/app/jobs/spree/exports/generate_job.rb +12 -0
  24. data/app/jobs/spree/products/auto_match_taxons_job.rb +14 -0
  25. data/app/jobs/spree/products/touch_taxons_job.rb +12 -0
  26. data/app/jobs/spree/reports/generate_job.rb +12 -0
  27. data/app/jobs/spree/stock_locations/stock_items/create_job.rb +1 -1
  28. data/app/jobs/spree/themes/duplicate_components_job.rb +59 -0
  29. data/app/jobs/spree/themes/screenshot_job.rb +81 -0
  30. data/app/jobs/spree/variants/remove_from_incomplete_orders_job.rb +2 -0
  31. data/app/jobs/spree/variants/remove_line_item_job.rb +2 -0
  32. data/app/mailers/spree/base_mailer.rb +51 -0
  33. data/app/mailers/spree/export_mailer.rb +19 -0
  34. data/app/mailers/spree/report_mailer.rb +20 -0
  35. data/app/mailers/spree/test_mailer.rb +8 -0
  36. data/app/models/action_text/rich_text_decorator.rb +11 -0
  37. data/app/models/action_text/video_embed.rb +13 -0
  38. data/app/models/acts_as_taggable_on/tag_decorator.rb +10 -0
  39. data/app/models/concerns/spree/calculated_adjustments.rb +2 -0
  40. data/app/models/concerns/spree/display_on.rb +13 -0
  41. data/app/models/concerns/spree/has_one_link.rb +42 -0
  42. data/app/models/concerns/spree/has_page_links.rb +53 -0
  43. data/app/models/concerns/spree/metadata.rb +3 -7
  44. data/app/models/concerns/spree/multi_searchable.rb +21 -0
  45. data/app/models/concerns/spree/multi_store_resource.rb +9 -0
  46. data/app/models/concerns/spree/number_as_param.rb +4 -2
  47. data/app/models/concerns/spree/parameterizable_name.rb +21 -0
  48. data/app/models/concerns/spree/previewable.rb +17 -0
  49. data/app/models/concerns/spree/product_scopes.rb +7 -7
  50. data/app/models/concerns/spree/stores/setup.rb +52 -0
  51. data/app/models/concerns/spree/stores/socials.rb +68 -0
  52. data/app/models/concerns/spree/user_address.rb +4 -0
  53. data/app/models/concerns/spree/user_methods.rb +61 -11
  54. data/app/models/concerns/spree/user_reporting.rb +14 -6
  55. data/app/models/concerns/spree/user_roles.rb +1 -1
  56. data/app/models/spree/ability.rb +4 -2
  57. data/app/models/spree/address.rb +122 -28
  58. data/app/models/spree/adjustment.rb +4 -1
  59. data/app/models/spree/asset/support/active_storage.rb +1 -1
  60. data/app/models/spree/asset.rb +18 -6
  61. data/app/models/spree/base.rb +38 -7
  62. data/app/models/spree/base_analytics_event_handler.rb +49 -0
  63. data/app/models/spree/calculator.rb +1 -1
  64. data/app/models/spree/classification.rb +10 -1
  65. data/app/models/spree/country.rb +1 -1
  66. data/app/models/spree/coupon_code.rb +38 -0
  67. data/app/models/spree/credit_card.rb +4 -3
  68. data/app/models/spree/current.rb +9 -0
  69. data/app/models/spree/custom_domain.rb +53 -0
  70. data/app/models/spree/customer_return.rb +13 -1
  71. data/app/models/spree/data_feed.rb +1 -1
  72. data/app/models/spree/digital.rb +5 -6
  73. data/app/models/spree/digital_link.rb +11 -6
  74. data/app/models/spree/export.rb +172 -0
  75. data/app/models/spree/exports/orders.rb +23 -0
  76. data/app/models/spree/exports/products.rb +35 -0
  77. data/app/models/spree/gateway/bogus.rb +5 -0
  78. data/app/models/spree/gateway.rb +14 -4
  79. data/app/models/spree/gateway_customer.rb +13 -0
  80. data/app/models/spree/image/configuration/active_storage.rb +1 -1
  81. data/app/models/spree/inventory_unit.rb +1 -1
  82. data/app/models/spree/legacy_user.rb +3 -1
  83. data/app/models/spree/line_item.rb +37 -2
  84. data/app/models/spree/log_entry.rb +1 -1
  85. data/app/models/spree/option_type.rb +40 -6
  86. data/app/models/spree/option_type_prototype.rb +1 -1
  87. data/app/models/spree/option_value.rb +35 -5
  88. data/app/models/spree/option_value_variant.rb +2 -2
  89. data/app/models/spree/order/address_book.rb +34 -15
  90. data/app/models/spree/order/checkout.rb +12 -2
  91. data/app/models/spree/order/currency_updater.rb +1 -1
  92. data/app/models/spree/order/digital.rb +14 -3
  93. data/app/models/spree/order/emails.rb +1 -1
  94. data/app/models/spree/order/payments.rb +1 -13
  95. data/app/models/spree/order/store_credit.rb +17 -5
  96. data/app/models/spree/order/webhooks.rb +1 -1
  97. data/app/models/spree/order.rb +179 -49
  98. data/app/models/spree/order_promotion.rb +1 -1
  99. data/app/models/spree/order_updater.rb +9 -3
  100. data/app/models/spree/page.rb +184 -0
  101. data/app/models/spree/page_block.rb +69 -0
  102. data/app/models/spree/page_blocks/buttons.rb +29 -0
  103. data/app/models/spree/page_blocks/heading.rb +18 -0
  104. data/app/models/spree/page_blocks/image.rb +17 -0
  105. data/app/models/spree/page_blocks/link.rb +21 -0
  106. data/app/models/spree/page_blocks/mega_nav.rb +33 -0
  107. data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +32 -0
  108. data/app/models/spree/page_blocks/nav.rb +15 -0
  109. data/app/models/spree/page_blocks/newsletter_form.rb +18 -0
  110. data/app/models/spree/page_blocks/products/buy_buttons.rb +12 -0
  111. data/app/models/spree/page_blocks/products/price.rb +18 -0
  112. data/app/models/spree/page_blocks/products/quantity_selector.rb +12 -0
  113. data/app/models/spree/page_blocks/products/share.rb +8 -0
  114. data/app/models/spree/page_blocks/products/title.rb +15 -0
  115. data/app/models/spree/page_blocks/products/variant_picker.rb +9 -0
  116. data/app/models/spree/page_blocks/subheading.rb +17 -0
  117. data/app/models/spree/page_blocks/text.rb +16 -0
  118. data/app/models/spree/page_link.rb +59 -0
  119. data/app/models/spree/page_section.rb +215 -0
  120. data/app/models/spree/page_sections/announcement_bar.rb +30 -0
  121. data/app/models/spree/page_sections/collection_banner.rb +18 -0
  122. data/app/models/spree/page_sections/custom_code.rb +11 -0
  123. data/app/models/spree/page_sections/featured_posts.rb +43 -0
  124. data/app/models/spree/page_sections/featured_product.rb +46 -0
  125. data/app/models/spree/page_sections/featured_taxon.rb +88 -0
  126. data/app/models/spree/page_sections/featured_taxons.rb +45 -0
  127. data/app/models/spree/page_sections/footer.rb +94 -0
  128. data/app/models/spree/page_sections/header.rb +62 -0
  129. data/app/models/spree/page_sections/image_banner.rb +38 -0
  130. data/app/models/spree/page_sections/image_with_text.rb +48 -0
  131. data/app/models/spree/page_sections/main_password_footer.rb +18 -0
  132. data/app/models/spree/page_sections/main_password_header.rb +20 -0
  133. data/app/models/spree/page_sections/newsletter.rb +47 -0
  134. data/app/models/spree/page_sections/page_title.rb +19 -0
  135. data/app/models/spree/page_sections/post_details.rb +19 -0
  136. data/app/models/spree/page_sections/post_grid.rb +19 -0
  137. data/app/models/spree/page_sections/product_details.rb +16 -0
  138. data/app/models/spree/page_sections/product_grid.rb +13 -0
  139. data/app/models/spree/page_sections/related_products.rb +60 -0
  140. data/app/models/spree/page_sections/rich_text.rb +20 -0
  141. data/app/models/spree/page_sections/taxon_banner.rb +18 -0
  142. data/app/models/spree/page_sections/taxon_grid.rb +17 -0
  143. data/app/models/spree/page_sections/video.rb +99 -0
  144. data/app/models/spree/pages/account.rb +15 -0
  145. data/app/models/spree/pages/cart.rb +9 -0
  146. data/app/models/spree/pages/checkout.rb +9 -0
  147. data/app/models/spree/pages/custom.rb +34 -0
  148. data/app/models/spree/pages/homepage.rb +68 -0
  149. data/app/models/spree/pages/login.rb +15 -0
  150. data/app/models/spree/pages/password.rb +57 -0
  151. data/app/models/spree/pages/post.rb +27 -0
  152. data/app/models/spree/pages/post_list.rb +32 -0
  153. data/app/models/spree/pages/product_details.rb +29 -0
  154. data/app/models/spree/pages/search_results.rb +43 -0
  155. data/app/models/spree/pages/shop_all.rb +36 -0
  156. data/app/models/spree/pages/taxon.rb +29 -0
  157. data/app/models/spree/pages/taxon_list.rb +41 -0
  158. data/app/models/spree/pages/wishlist.rb +11 -0
  159. data/app/models/spree/payment/gateway_options.rb +13 -15
  160. data/app/models/spree/payment/processing.rb +1 -1
  161. data/app/models/spree/payment/webhooks.rb +1 -1
  162. data/app/models/spree/payment.rb +61 -12
  163. data/app/models/spree/payment_capture_event.rb +1 -1
  164. data/app/models/spree/payment_method/store_credit.rb +9 -1
  165. data/app/models/spree/payment_method.rb +26 -8
  166. data/app/models/spree/payment_source.rb +2 -2
  167. data/app/models/spree/post.rb +108 -0
  168. data/app/models/spree/post_category.rb +33 -0
  169. data/app/models/spree/preference.rb +1 -1
  170. data/app/models/spree/price.rb +10 -3
  171. data/app/models/spree/product/webhooks.rb +1 -1
  172. data/app/models/spree/product.rb +325 -54
  173. data/app/models/spree/product_option_type.rb +1 -1
  174. data/app/models/spree/product_promotion_rule.rb +1 -1
  175. data/app/models/spree/product_property.rb +4 -1
  176. data/app/models/spree/promotion/actions/create_line_items.rb +37 -2
  177. data/app/models/spree/promotion/rules/country.rb +22 -4
  178. data/app/models/spree/promotion/rules/currency.rb +21 -0
  179. data/app/models/spree/promotion/rules/item_total.rb +12 -3
  180. data/app/models/spree/promotion/rules/option_value.rb +5 -20
  181. data/app/models/spree/promotion/rules/product.rb +33 -1
  182. data/app/models/spree/promotion/rules/taxon.rb +31 -0
  183. data/app/models/spree/promotion/rules/user.rb +33 -4
  184. data/app/models/spree/promotion.rb +136 -15
  185. data/app/models/spree/promotion_action.rb +31 -1
  186. data/app/models/spree/promotion_action_line_item.rb +1 -1
  187. data/app/models/spree/promotion_category.rb +1 -1
  188. data/app/models/spree/promotion_handler/cart.rb +1 -1
  189. data/app/models/spree/promotion_handler/coupon.rb +46 -8
  190. data/app/models/spree/promotion_handler/free_shipping.rb +1 -1
  191. data/app/models/spree/promotion_handler/promotion_duplicator.rb +6 -5
  192. data/app/models/spree/promotion_rule.rb +23 -1
  193. data/app/models/spree/promotion_rule_taxon.rb +1 -1
  194. data/app/models/spree/promotion_rule_user.rb +1 -1
  195. data/app/models/spree/property.rb +11 -3
  196. data/app/models/spree/property_prototype.rb +1 -1
  197. data/app/models/spree/prototype.rb +1 -1
  198. data/app/models/spree/prototype_taxon.rb +1 -1
  199. data/app/models/spree/refund.rb +24 -4
  200. data/app/models/spree/refund_reason.rb +12 -2
  201. data/app/models/spree/reimbursement/credit.rb +1 -1
  202. data/app/models/spree/reimbursement/emails.rb +1 -1
  203. data/app/models/spree/reimbursement.rb +5 -3
  204. data/app/models/spree/reimbursement_type.rb +1 -1
  205. data/app/models/spree/report.rb +110 -0
  206. data/app/models/spree/report_line_item.rb +27 -0
  207. data/app/models/spree/report_line_items/products_performance.rb +76 -0
  208. data/app/models/spree/report_line_items/sales_total.rb +49 -0
  209. data/app/models/spree/reports/products_performance.rb +44 -0
  210. data/app/models/spree/reports/sales_total.rb +14 -0
  211. data/app/models/spree/return_authorization.rb +4 -1
  212. data/app/models/spree/return_authorization_reason.rb +1 -1
  213. data/app/models/spree/return_item.rb +2 -1
  214. data/app/models/spree/role.rb +5 -2
  215. data/app/models/spree/role_user.rb +2 -2
  216. data/app/models/spree/shipment/emails.rb +1 -1
  217. data/app/models/spree/shipment/webhooks.rb +1 -1
  218. data/app/models/spree/shipment.rb +14 -4
  219. data/app/models/spree/shipping_category.rb +1 -1
  220. data/app/models/spree/shipping_method.rb +48 -8
  221. data/app/models/spree/shipping_method_category.rb +1 -1
  222. data/app/models/spree/shipping_method_zone.rb +1 -1
  223. data/app/models/spree/shipping_rate.rb +21 -3
  224. data/app/models/spree/state.rb +1 -1
  225. data/app/models/spree/state_change.rb +1 -1
  226. data/app/models/spree/stock_item/webhooks.rb +1 -1
  227. data/app/models/spree/stock_item.rb +9 -6
  228. data/app/models/spree/stock_location.rb +35 -8
  229. data/app/models/spree/stock_movement/webhooks.rb +1 -1
  230. data/app/models/spree/stock_movement.rb +9 -3
  231. data/app/models/spree/stock_transfer.rb +41 -3
  232. data/app/models/spree/store.rb +345 -72
  233. data/app/models/spree/store_credit.rb +12 -4
  234. data/app/models/spree/store_credit_category.rb +1 -1
  235. data/app/models/spree/store_credit_event.rb +21 -1
  236. data/app/models/spree/store_credit_type.rb +1 -1
  237. data/app/models/spree/store_payment_method.rb +1 -1
  238. data/app/models/spree/store_product.rb +1 -1
  239. data/app/models/spree/store_promotion.rb +1 -1
  240. data/app/models/spree/tax_category.rb +15 -1
  241. data/app/models/spree/tax_rate.rb +1 -1
  242. data/app/models/spree/taxon.rb +210 -27
  243. data/app/models/spree/taxon_image/configuration/active_storage.rb +1 -1
  244. data/app/models/spree/taxon_rule.rb +25 -0
  245. data/app/models/spree/taxon_rules/available_on.rb +20 -0
  246. data/app/models/spree/taxon_rules/sale.rb +16 -0
  247. data/app/models/spree/taxon_rules/tag.rb +19 -0
  248. data/app/models/spree/taxonomy.rb +3 -2
  249. data/app/models/spree/theme.rb +200 -0
  250. data/app/models/spree/themes/default.rb +94 -0
  251. data/app/models/spree/variant/webhooks.rb +1 -1
  252. data/app/models/spree/variant.rb +211 -62
  253. data/app/models/spree/wished_item.rb +1 -1
  254. data/app/models/spree/wishlist.rb +1 -1
  255. data/app/models/spree/zone.rb +1 -1
  256. data/app/models/spree/zone_member.rb +1 -1
  257. data/app/presenters/spree/csv/order_line_item_presenter.rb +145 -0
  258. data/app/presenters/spree/csv/product_presenter.rb +63 -0
  259. data/app/presenters/spree/csv/product_variant_presenter.rb +130 -0
  260. data/app/services/spree/addresses/create.rb +31 -6
  261. data/app/services/spree/addresses/helper.rb +7 -4
  262. data/app/services/spree/addresses/update.rb +79 -12
  263. data/app/services/spree/cart/remove_out_of_stock_items.rb +56 -0
  264. data/app/services/spree/checkout/add_store_credit.rb +6 -1
  265. data/app/services/spree/checkout/advance.rb +44 -4
  266. data/app/services/spree/checkout/select_shipping_method.rb +2 -0
  267. data/app/services/spree/coupon_codes/bulk_generate.rb +37 -0
  268. data/app/services/spree/coupon_codes/coupon_codes_handler.rb +34 -0
  269. data/app/services/spree/orders/create_user_account.rb +70 -0
  270. data/app/services/spree/orders/update_contact_information.rb +19 -0
  271. data/app/services/spree/products/auto_match_taxons.rb +64 -0
  272. data/app/services/spree/products/duplicator.rb +121 -0
  273. data/app/services/spree/products/prepare_nested_attributes.rb +169 -0
  274. data/app/services/spree/seeds/admin_user.rb +22 -0
  275. data/app/services/spree/seeds/all.rb +1 -0
  276. data/app/services/spree/seeds/stores.rb +5 -10
  277. data/app/services/spree/seeds/zones.rb +2 -0
  278. data/app/services/spree/tags/bulk_add.rb +38 -0
  279. data/app/services/spree/tags/bulk_remove.rb +24 -0
  280. data/app/services/spree/taxons/add_products.rb +39 -0
  281. data/app/services/spree/taxons/regenerate_products.rb +53 -0
  282. data/app/services/spree/taxons/remove_products.rb +53 -0
  283. data/app/services/spree/taxons/touch_featured_sections.rb +21 -0
  284. data/app/services/spree/themes/duplicator.rb +40 -0
  285. data/app/services/spree/variants/remove_line_items.rb +1 -1
  286. data/app/sorters/spree/classifications/sort.rb +68 -0
  287. data/app/sorters/spree/products/sort.rb +2 -3
  288. data/app/views/action_text/video_embeds/_thumbnail.html.erb +1 -0
  289. data/app/views/action_text/video_embeds/_video_embed.html.erb +3 -0
  290. data/app/views/active_storage/blobs/_blob.html.erb +20 -0
  291. data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
  292. data/app/views/layouts/spree/base_mailer.html.erb +46 -0
  293. data/app/views/spree/addresses/_form.html.erb +58 -0
  294. data/app/views/spree/addresses/_suggestions_box.erb +14 -0
  295. data/app/views/spree/export_mailer/export_done.html.erb +15 -0
  296. data/app/views/spree/report_mailer/report_done.html.erb +15 -0
  297. data/app/views/spree/shared/_base_mailer_footer.html.erb +12 -0
  298. data/app/views/spree/shared/_base_mailer_header.html.erb +6 -0
  299. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +456 -0
  300. data/app/views/spree/shared/_google_places_api_loader.html.erb +7 -0
  301. data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
  302. data/app/views/spree/shared/_mailer_logo.html.erb +41 -0
  303. data/app/views/spree/shared/_payment.html.erb +41 -0
  304. data/app/views/spree/test_mailer/test_email.html.erb +40 -0
  305. data/app/views/spree/test_mailer/test_email.text.erb +4 -0
  306. data/config/i18n-tasks.yml +178 -0
  307. data/config/importmap.rb +14 -0
  308. data/config/initializers/acts_as_taggable_on.rb +2 -0
  309. data/config/initializers/inflections.rb +2 -0
  310. data/config/initializers/mobility.rb +4 -0
  311. data/config/initializers/oembed.rb +1 -0
  312. data/config/locales/en.yml +823 -413
  313. data/config/routes.rb +6 -5
  314. data/db/migrate/20210914000000_spree_four_three.rb +0 -79
  315. data/db/migrate/20240913143518_change_default_value_of_spree_option_types_filterable.rb +5 -0
  316. data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +5 -0
  317. data/db/migrate/20240915144935_add_position_to_spree_properties.rb +6 -0
  318. data/db/migrate/20241004181911_create_spree_coupon_codes.rb +15 -0
  319. data/db/migrate/20241005093437_add_multi_code_to_spree_promotions.rb +14 -0
  320. data/db/migrate/20241014140140_translate_rich_texts.rb +17 -0
  321. data/db/migrate/20241030134309_create_spree_exports.rb +23 -0
  322. data/db/migrate/20241104083457_migrate_spree_promotion_rules_option_value_eligible_values.rb +16 -0
  323. data/db/migrate/20241123110646_add_estimated_transit_fields_to_spree_shipping_methods.rb +6 -0
  324. data/db/migrate/20241127193411_create_spree_taxon_rules.rb +13 -0
  325. data/db/migrate/20241127223627_add_rules_match_policy_and_sort_order_to_spree_taxons.rb +6 -0
  326. data/db/migrate/20241128103947_add_automatic_to_spree_taxons.rb +5 -0
  327. data/db/migrate/20241218183905_add_gateway_customer_profile_id_to_spree_payment_sources.rb +5 -0
  328. data/db/migrate/20250107220432_add_accept_marketing_and_signup_for_an_account_to_spree_orders.rb +6 -0
  329. data/db/migrate/20250110171203_add_quick_checkout_to_spree_addresses.rb +6 -0
  330. data/db/migrate/20250113180019_add_preferences_to_spree_stores.rb +5 -0
  331. data/db/migrate/20250114193857_add_metadata_to_spree_stores.rb +13 -0
  332. data/db/migrate/20250119165904_create_spree_custom_domains.rb +22 -0
  333. data/db/migrate/20250120094216_create_page_builder_models.rb +78 -0
  334. data/db/migrate/20250120152208_add_default_locale_to_action_text_rich_texts.rb +7 -0
  335. data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +33 -0
  336. data/db/migrate/20250122113708_add_first_and_last_name_to_spree_admin_class.rb +9 -0
  337. data/db/migrate/20250123135358_add_custom_code_fields_to_spree_store.rb +7 -0
  338. data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +5 -0
  339. data/db/migrate/20250127112758_add_latitude_and_longitude_to_spree_addresses.rb +6 -0
  340. data/db/migrate/20250127151258_add_phone_to_spree_users.rb +5 -0
  341. data/db/migrate/20250204162453_create_spree_reports.rb +13 -0
  342. data/db/migrate/20250207084000_add_accepts_email_marketing_field_to_spree_users_table.rb +6 -0
  343. data/db/migrate/20250217171018_create_action_text_video_embeds.rb +11 -0
  344. data/db/migrate/20250304115943_add_performed_by_to_spree_reimbursements.rb +5 -0
  345. data/db/migrate/20250305121352_remove_page_builder_indices.rb +11 -0
  346. data/db/migrate/20250305121657_remove_spree_posts_indices.rb +7 -0
  347. data/db/migrate/20250311105934_create_spree_gateway_customers.rb +18 -0
  348. data/db/migrate/20250312202705_add_unique_index_on_promotion_rules_associations.rb +75 -0
  349. data/db/migrate/20250313104226_add_user_type_to_spree_role_users.rb +18 -0
  350. data/db/migrate/20250313175830_add_unique_index_on_promotion_action_line_items.rb +29 -0
  351. data/db/migrate/20250314144210_create_spree_taggings_and_spree_tags.rb +38 -0
  352. data/lib/generators/spree/authentication/custom/custom_generator.rb +49 -0
  353. data/lib/generators/spree/authentication/custom/templates/authentication_helpers.rb.tt +50 -0
  354. data/lib/generators/spree/authentication/devise/devise_generator.rb +57 -0
  355. data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +50 -0
  356. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  357. data/lib/generators/spree/dummy/templates/rails/database.yml +1 -0
  358. data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
  359. data/lib/generators/spree/install/install_generator.rb +21 -36
  360. data/lib/generators/spree/install/templates/config/initializers/spree.rb +40 -6
  361. data/lib/normalize_string.rb +18 -0
  362. data/lib/spree/analytics.rb +11 -0
  363. data/lib/spree/core/components.rb +1 -1
  364. data/lib/spree/core/configuration.rb +14 -11
  365. data/lib/spree/core/controller_helpers/auth.rb +0 -26
  366. data/lib/spree/core/controller_helpers/order.rb +77 -12
  367. data/lib/spree/core/controller_helpers/search.rb +2 -0
  368. data/lib/spree/core/controller_helpers/store.rb +0 -5
  369. data/lib/spree/core/controller_helpers/strong_parameters.rb +4 -0
  370. data/lib/spree/core/controller_helpers/turbo.rb +19 -0
  371. data/lib/spree/core/dependencies.rb +3 -5
  372. data/lib/spree/core/engine.rb +158 -7
  373. data/lib/spree/core/preferences/configuration.rb +2 -44
  374. data/lib/spree/core/preferences/preferable.rb +9 -0
  375. data/lib/spree/core/preferences/preferable_class_methods.rb +11 -1
  376. data/lib/spree/core/preferences/runtime_configuration.rb +13 -2
  377. data/lib/spree/core/search/base.rb +2 -0
  378. data/lib/spree/core/version.rb +1 -1
  379. data/lib/spree/core.rb +61 -11
  380. data/lib/spree/i18n.rb +5 -8
  381. data/lib/spree/migrations.rb +1 -1
  382. data/lib/spree/permitted_attributes.rb +24 -15
  383. data/lib/spree/testing_support/authorization_helpers.rb +9 -6
  384. data/lib/spree/testing_support/capybara_config.rb +11 -0
  385. data/lib/spree/testing_support/common_rake.rb +20 -12
  386. data/lib/spree/testing_support/factories/calculator_factory.rb +16 -0
  387. data/lib/spree/testing_support/factories/country_factory.rb +8 -0
  388. data/lib/spree/testing_support/factories/coupon_code_factory.rb +7 -0
  389. data/lib/spree/testing_support/factories/custom_domain_factory.rb +7 -0
  390. data/lib/spree/testing_support/factories/export_factory.rb +32 -0
  391. data/lib/spree/testing_support/factories/gateway_customer_factory.rb +7 -0
  392. data/lib/spree/testing_support/factories/order_factory.rb +14 -3
  393. data/lib/spree/testing_support/factories/page_block_factory.rb +21 -0
  394. data/lib/spree/testing_support/factories/page_factory.rb +33 -0
  395. data/lib/spree/testing_support/factories/page_link_factory.rb +7 -0
  396. data/lib/spree/testing_support/factories/page_section_factory.rb +24 -0
  397. data/lib/spree/testing_support/factories/payment_factory.rb +2 -2
  398. data/lib/spree/testing_support/factories/post_category_factory.rb +7 -0
  399. data/lib/spree/testing_support/factories/post_factory.rb +10 -0
  400. data/lib/spree/testing_support/factories/product_factory.rb +3 -8
  401. data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
  402. data/lib/spree/testing_support/factories/promotion_action_factory.rb +5 -0
  403. data/lib/spree/testing_support/factories/promotion_factory.rb +7 -9
  404. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
  405. data/lib/spree/testing_support/factories/property_factory.rb +1 -1
  406. data/lib/spree/testing_support/factories/report_factory.rb +33 -0
  407. data/lib/spree/testing_support/factories/role_user_factory.rb +7 -0
  408. data/lib/spree/testing_support/factories/shipping_method_factory.rb +9 -0
  409. data/lib/spree/testing_support/factories/stock_transfer_factory.rb +5 -2
  410. data/lib/spree/testing_support/factories/store_factory.rb +6 -9
  411. data/lib/spree/testing_support/factories/taxon_factory.rb +13 -0
  412. data/lib/spree/testing_support/factories/taxon_rule_factory.rb +38 -0
  413. data/lib/spree/testing_support/factories/theme_factory.rb +14 -0
  414. data/lib/spree/testing_support/factories/user_factory.rb +13 -11
  415. data/lib/spree/testing_support/factories/variant_factory.rb +23 -5
  416. data/lib/spree/testing_support/jobs.rb +1 -7
  417. data/lib/spree/testing_support/metadata.rb +13 -1
  418. data/lib/spree/testing_support/order_walkthrough.rb +1 -7
  419. data/lib/spree/testing_support/preferences.rb +1 -4
  420. data/lib/spree/testing_support/store.rb +26 -0
  421. data/lib/spree_core.rb +1 -0
  422. data/vendor/javascript/@rails--request.js.js +4 -0
  423. data/vendor/javascript/@stimulus-components--auto-submit.js +4 -0
  424. data/vendor/javascript/stimulus-reveal-controller.js +4 -0
  425. data/vendor/javascript/tailwindcss-stimulus-components.js +4 -0
  426. metadata +340 -197
  427. data/Gemfile +0 -3
  428. data/app/finders/spree/cms_pages/find.rb +0 -41
  429. data/app/finders/spree/menus/find.rb +0 -11
  430. data/app/models/concerns/spree/display_link.rb +0 -30
  431. data/app/models/spree/cms/pages/feature_page.rb +0 -7
  432. data/app/models/spree/cms/pages/homepage.rb +0 -20
  433. data/app/models/spree/cms/pages/standard_page.rb +0 -4
  434. data/app/models/spree/cms/sections/featured_article.rb +0 -22
  435. data/app/models/spree/cms/sections/hero_image.rb +0 -38
  436. data/app/models/spree/cms/sections/image_gallery.rb +0 -97
  437. data/app/models/spree/cms/sections/product_carousel.rb +0 -14
  438. data/app/models/spree/cms/sections/rich_text_content.rb +0 -13
  439. data/app/models/spree/cms/sections/side_by_side_images.rb +0 -68
  440. data/app/models/spree/cms_page.rb +0 -70
  441. data/app/models/spree/cms_section.rb +0 -69
  442. data/app/models/spree/cms_section_image.rb +0 -9
  443. data/app/models/spree/cms_section_image_one.rb +0 -4
  444. data/app/models/spree/cms_section_image_three.rb +0 -4
  445. data/app/models/spree/cms_section_image_two.rb +0 -4
  446. data/app/models/spree/icon.rb +0 -7
  447. data/app/models/spree/linkable/homepage.rb +0 -3
  448. data/app/models/spree/linkable/uri.rb +0 -3
  449. data/app/models/spree/menu.rb +0 -66
  450. data/app/models/spree/menu_item.rb +0 -72
  451. data/brakeman.ignore +0 -328
  452. data/db/migrate/20211201202851_update_linkable_resource_types.rb +0 -10
  453. data/db/migrate/20220329113557_fix_cms_pages_unique_indexes.rb +0 -8
  454. data/lib/generators/spree/custom_authentication/custom_authentication_generator.rb +0 -23
  455. data/lib/generators/spree/custom_authentication/templates/authentication_helpers.rb.tt +0 -23
  456. data/lib/generators/spree/custom_user/custom_user_generator.rb +0 -46
  457. data/lib/generators/spree/custom_user/templates/current_user_helpers.rb.tt +0 -15
  458. data/lib/generators/spree/custom_user/templates/initializer.rb.tt +0 -1
  459. data/lib/generators/spree/custom_user/templates/migration.rb.tt +0 -7
  460. data/lib/generators/spree/dummy/templates/package.json +0 -12
  461. data/lib/spree/core/product_duplicator.rb +0 -85
  462. data/lib/spree/core/runtime_configuration.rb +0 -10
  463. data/lib/spree/testing_support/factories/cms_page_factory.rb +0 -20
  464. data/lib/spree/testing_support/factories/cms_section_factory.rb +0 -31
  465. data/lib/spree/testing_support/factories/icon_factory.rb +0 -9
  466. data/lib/spree/testing_support/factories/menu_factory.rb +0 -16
  467. data/lib/spree/testing_support/factories/menu_item_factory.rb +0 -10
  468. data/script/rails +0 -9
  469. data/spec/fixtures/favicon.ico +0 -0
  470. data/spec/fixtures/files/icon_256x256.gif +0 -0
  471. data/spec/fixtures/files/icon_256x256.png +0 -0
  472. data/spec/fixtures/files/icon_512x512.png +0 -0
  473. data/spec/fixtures/files/img_256x128.png +0 -0
  474. data/spec/fixtures/text-file.txt +0 -1
  475. data/spec/fixtures/thinking-cat.jpg +0 -0
  476. data/spree_core.gemspec +0 -62
@@ -0,0 +1,33 @@
1
+ FactoryBot.define do
2
+ factory :page, class: Spree::Page do
3
+ type { 'Spree::Page' }
4
+ pageable { Spree::Theme.first || create(:theme) }
5
+ sequence(:name) { |n| "Page #{n}" }
6
+ meta_description { 'Page Description' }
7
+
8
+ trait :homepage do
9
+ name { 'Homepage' }
10
+ type { 'Spree::Pages::Homepage' }
11
+ end
12
+
13
+ trait :account do
14
+ type { 'Spree::Pages::Account' }
15
+ name { 'Account' }
16
+ end
17
+
18
+ trait :preview do
19
+ parent { create(:page) }
20
+ end
21
+
22
+ trait :for_store do
23
+ pageable { Spree::Store.default }
24
+ end
25
+ end
26
+
27
+ factory :custom_page, class: Spree::Pages::Custom do
28
+ type { 'Spree::Pages::Custom' }
29
+ pageable { Spree::Store.default }
30
+ sequence(:name) { |n| "Custom Page #{n}" }
31
+ meta_description { 'Page Description' }
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :page_link, class: Spree::PageLink do
3
+ parent { Spree::PageSections::Header.first }
4
+ linkable { Spree::Page.first }
5
+ sequence(:label) { |n| "Page Link #{n}" }
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ FactoryBot.define do
2
+ factory :page_section, class: Spree::PageSection do
3
+ pageable { Spree::Page.find_by!(name: 'Homepage') }
4
+ pageable_type { 'Spree::Page' }
5
+
6
+ trait :without_links do
7
+ do_not_create_links { true }
8
+ end
9
+
10
+ factory :featured_taxons_page_section, class: Spree::PageSections::FeaturedTaxons
11
+
12
+ factory :featured_taxon_page_section, class: Spree::PageSections::FeaturedTaxon
13
+
14
+ factory :header_page_section, class: Spree::PageSections::Header
15
+
16
+ factory :announcement_bar_page_section, class: Spree::PageSections::AnnouncementBar
17
+
18
+ factory :rich_text_page_section, class: Spree::PageSections::RichText
19
+
20
+ factory :newsletter_page_section, class: Spree::PageSections::Newsletter
21
+
22
+ factory :video_page_section, class: Spree::PageSections::Video
23
+ end
24
+ end
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :payment, class: Spree::Payment do
3
- order
3
+ order { create(:order, total: amount) }
4
4
  amount { 45.75 }
5
5
  state { 'checkout' }
6
6
  response_code { '12345' }
@@ -18,7 +18,7 @@ FactoryBot.define do
18
18
 
19
19
  factory :check_payment, class: Spree::Payment do
20
20
  amount { 45.75 }
21
- order
21
+ order { create(:order, total: 45.75) }
22
22
 
23
23
  association(:payment_method, factory: :check_payment_method)
24
24
  end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :post_category, class: Spree::PostCategory do
3
+ sequence(:title) { |n| "Category ##{n + 1}" }
4
+ description { FFaker::Lorem.sentence }
5
+ store { Spree::Store.default || create(:store) }
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ FactoryBot.define do
2
+ factory :post, class: Spree::Post do
3
+ post_category { create(:post_category) }
4
+ title { FFaker::Lorem.sentence }
5
+ content { FFaker::Lorem.paragraph }
6
+ published_at { Time.current }
7
+ author { create(:admin_user) }
8
+ store { Spree::Store.default || create(:store) }
9
+ end
10
+ end
@@ -10,18 +10,13 @@ FactoryBot.define do
10
10
  deleted_at { nil }
11
11
  shipping_category { |r| Spree::ShippingCategory.first || r.association(:shipping_category) }
12
12
  status { 'active' }
13
+ stores { [Spree::Store.default] }
13
14
 
14
15
  # ensure stock item will be created for this products master
15
16
  # also attach this product to the default store if no stores are passed in
16
- before(:create) do |product|
17
+ before(:create) do |_product|
17
18
  create(:stock_location) unless Spree::StockLocation.any?
18
-
19
- if product.stores.empty?
20
- default_store = Spree::Store.default.persisted? ? Spree::Store.default : nil
21
- store = default_store || create(:store)
22
-
23
- product.stores << [store]
24
- end
19
+ create(:store, default: true) unless Spree::Store.any?
25
20
  end
26
21
  after(:create) do |product|
27
22
  Spree::StockLocation.all.each { |stock_location| stock_location.propagate_variant(product.master) unless stock_location.stock_items.exists?(variant: product.master) }
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :product_property, class: Spree::ProductProperty do
3
- product { create(:product, stores: [create(:store)]) }
3
+ product { create(:product, stores: [Spree::Store.default]) }
4
4
  value { "val-#{rand(50)}" }
5
5
  property
6
6
  end
@@ -2,4 +2,9 @@ FactoryBot.define do
2
2
  factory :promotion_action, class: Spree::PromotionAction do
3
3
  association :promotion
4
4
  end
5
+
6
+ factory :promotion_action_create_adjustment, class: Spree::Promotion::Actions::CreateAdjustment do
7
+ association :promotion
8
+ association :calculator, factory: :flat_rate_calculator
9
+ end
5
10
  end
@@ -5,19 +5,21 @@ FactoryBot.define do
5
5
  end
6
6
 
7
7
  after(:create) do |promotion, evaluator|
8
- rule = Spree::Promotion::Rules::ItemTotal.create!(
8
+ Spree::Promotion::Rules::ItemTotal.create!(
9
+ promotion: promotion,
9
10
  preferred_operator_min: 'gte',
10
11
  preferred_operator_max: 'lte',
11
12
  preferred_amount_min: evaluator.item_total_threshold_amount,
12
13
  preferred_amount_max: evaluator.item_total_threshold_amount + 100
13
14
  )
14
- promotion.rules << rule
15
- promotion.save!
16
15
  end
17
16
  end
18
17
 
19
18
  factory :promotion, class: Spree::Promotion do
20
19
  name { 'Promo' }
20
+ sequence :code do |n|
21
+ "CODE-#{n}"
22
+ end
21
23
 
22
24
  before(:create) do |promotion, _evaluator|
23
25
  if promotion.stores.empty?
@@ -58,9 +60,7 @@ FactoryBot.define do
58
60
  after(:create) do |promotion, evaluator|
59
61
  calculator = Spree::Calculator::FlatRate.new
60
62
  calculator.preferred_amount = evaluator.weighted_order_adjustment_amount
61
- action = Spree::Promotion::Actions::CreateAdjustment.create!(calculator: calculator)
62
- promotion.actions << action
63
- promotion.save!
63
+ Spree::Promotion::Actions::CreateAdjustment.create!(calculator: calculator, promotion: promotion)
64
64
  end
65
65
  end
66
66
 
@@ -71,9 +71,7 @@ FactoryBot.define do
71
71
  name { 'Free Shipping Promotion' }
72
72
 
73
73
  after(:create) do |promotion|
74
- action = Spree::Promotion::Actions::FreeShipping.new
75
- action.promotion = promotion
76
- action.save
74
+ Spree::Promotion::Actions::FreeShipping.create!(promotion: promotion)
77
75
  end
78
76
 
79
77
  factory :free_shipping_promotion_with_item_total_rule, traits: [:with_item_total_rule]
@@ -2,4 +2,16 @@ FactoryBot.define do
2
2
  factory :promotion_rule, class: Spree::PromotionRule do
3
3
  association :promotion
4
4
  end
5
+
6
+ factory :promotion_rule_user, class: Spree::Promotion::Rules::User do
7
+ association :promotion
8
+ end
9
+
10
+ factory :promotion_rule_product, class: Spree::Promotion::Rules::Product do
11
+ association :promotion
12
+ end
13
+
14
+ factory :promotion_rule_taxon, class: Spree::Promotion::Rules::Taxon do
15
+ association :promotion
16
+ end
5
17
  end
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :property, class: Spree::Property do
3
- name { 'baseball_cap_color' }
3
+ sequence(:name) { |n| "baseball_cap_color_#{n}" }
4
4
  presentation { 'cap color' }
5
5
 
6
6
  trait :filterable do
@@ -0,0 +1,33 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: spree_reports
4
+ #
5
+ # id :bigint not null, primary key
6
+ # type :string
7
+ # currency :string
8
+ # date_from :datetime
9
+ # date_to :datetime
10
+ # created_at :datetime not null
11
+ # updated_at :datetime not null
12
+ # store_id :bigint not null
13
+ # user_id :bigint
14
+ #
15
+ FactoryBot.define do
16
+ factory :report, class: 'Spree::Reports::SalesTotal' do
17
+ store { create(:store) }
18
+ user { create(:admin_user) }
19
+ type { 'Spree::Reports::SalesTotal' }
20
+ currency { 'USD' }
21
+ date_from { 1.month.ago }
22
+ date_to { Time.current }
23
+ end
24
+
25
+ factory :products_performance_report, class: 'Spree::Reports::ProductsPerformance' do
26
+ store { create(:store) }
27
+ user { create(:admin_user) }
28
+ type { 'Spree::Reports::ProductsPerformance' }
29
+ currency { 'USD' }
30
+ date_from { 1.month.ago }
31
+ date_to { Time.current }
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :role_user, class: 'Spree::RoleUser' do
3
+ association :role, factory: :role
4
+ association :user, factory: :user
5
+ user_type { user.class.to_s }
6
+ end
7
+ end
@@ -18,5 +18,14 @@ FactoryBot.define do
18
18
  factory :free_shipping_method, class: Spree::ShippingMethod do
19
19
  association(:calculator, factory: :shipping_no_amount_calculator, strategy: :build)
20
20
  end
21
+
22
+ factory :digital_shipping_method, class: Spree::ShippingMethod do
23
+ association(:calculator, factory: :digital_shipping_calculator, strategy: :build)
24
+
25
+ before(:create) do |shipping_method|
26
+ shipping_method.shipping_categories.delete_all
27
+ shipping_method.shipping_categories << create(:shipping_category, name: 'Digital')
28
+ end
29
+ end
21
30
  end
22
31
  end
@@ -1,9 +1,12 @@
1
1
  FactoryBot.define do
2
2
  factory :stock_transfer, class: Spree::StockTransfer do
3
- destination_location {}
3
+ association :source_location, factory: :stock_location
4
+ association :destination_location, factory: :stock_location
5
+
6
+ stock_movements { [build(:stock_movement)] }
7
+
4
8
  number {}
5
9
  reference {}
6
- source_location {}
7
10
  type {}
8
11
  end
9
12
  end
@@ -13,17 +13,14 @@ FactoryBot.define do
13
13
  twitter { 'spreecommerce' }
14
14
  instagram { 'spreecommerce' }
15
15
  meta_description { 'Sample store description.' }
16
- digital_asset_authorized_clicks { 5 }
17
- digital_asset_authorized_days { 7 }
18
16
 
19
17
  trait :with_favicon do
20
- transient do
21
- filepath { Spree::Core::Engine.root.join('spec', 'fixtures', 'favicon.ico') }
22
- image_type { 'image/x-icon' }
23
- end
24
-
25
- favicon_image do
26
- create(:favicon_image, attachment: Rack::Test::UploadedFile.new(filepath, image_type))
18
+ after(:build) do |store|
19
+ store.favicon_image.attach(
20
+ io: File.open(Spree::Core::Engine.root.join('spec', 'fixtures', 'thinking-cat.jpg')),
21
+ filename: 'thinking-cat.jpg',
22
+ content_type: 'image/jpeg'
23
+ )
27
24
  end
28
25
  end
29
26
  end
@@ -5,5 +5,18 @@ FactoryBot.define do
5
5
  association :taxonomy, strategy: :create
6
6
  association :icon, factory: :taxon_image
7
7
  parent_id { taxonomy.root.id }
8
+
9
+ trait :with_description do
10
+ description { '<div>Test <strong>description</strong></div>' }
11
+ end
12
+ end
13
+
14
+ factory :automatic_taxon, parent: :taxon do
15
+ automatic { true }
16
+ rules_match_policy { :all }
17
+
18
+ trait :any_match_policy do
19
+ rules_match_policy { :any }
20
+ end
8
21
  end
9
22
  end
@@ -0,0 +1,38 @@
1
+ FactoryBot.define do
2
+ factory :sale_taxon_rule, class: Spree::TaxonRules::Sale do
3
+ value { true }
4
+ trait :is_equal_to do
5
+ match_policy { :is_equal_to }
6
+ end
7
+
8
+ trait :is_not_equal_to do
9
+ match_policy { :is_not_equal_to }
10
+ end
11
+
12
+ trait :contains do
13
+ match_policy { :contains }
14
+ end
15
+
16
+ trait :does_not_contain do
17
+ match_policy { :does_not_contain }
18
+ end
19
+ end
20
+
21
+ factory :tag_taxon_rule, class: Spree::TaxonRules::Tag do
22
+ trait :is_equal_to do
23
+ match_policy { :is_equal_to }
24
+ end
25
+
26
+ trait :is_not_equal_to do
27
+ match_policy { :is_not_equal_to }
28
+ end
29
+
30
+ trait :contains do
31
+ match_policy { :contains }
32
+ end
33
+
34
+ trait :does_not_contain do
35
+ match_policy { :does_not_contain }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ FactoryBot.define do
2
+ factory :theme, class: Spree::Theme do
3
+ sequence(:name) { |n| "Theme #{n}#{Kernel.rand(9999)}" }
4
+ store { Spree::Store.default || create(:store, default: true) }
5
+
6
+ trait :blank do
7
+ duplicating { true }
8
+ end
9
+
10
+ trait :preview do
11
+ parent { create(:theme) }
12
+ end
13
+ end
14
+ end
@@ -1,25 +1,16 @@
1
1
  FactoryBot.define do
2
- sequence :user_authentication_token do |n|
3
- "xxxx#{Time.current.to_i}#{rand(1000)}#{n}xxxxxxxxxxxxx"
4
- end
5
-
6
2
  factory :user, class: Spree.user_class do
7
3
  email { generate(:random_email) }
8
4
  login { email }
9
5
  password { 'secret' }
10
6
  password_confirmation { password }
11
- authentication_token { generate(:user_authentication_token) } if Spree.user_class.attribute_method? :authentication_token
12
7
 
13
- first_name { FFaker::Name.first_name }
14
- last_name { FFaker::Name.last_name }
8
+ first_name { FFaker::Name.first_name } if Spree.user_class.attribute_method?(:first_name)
9
+ last_name { FFaker::Name.last_name } if Spree.user_class.attribute_method?(:last_name)
15
10
 
16
11
  public_metadata { {} }
17
12
  private_metadata { {} }
18
13
 
19
- factory :admin_user do
20
- spree_roles { [Spree::Role.find_by(name: 'admin') || create(:role, name: 'admin')] }
21
- end
22
-
23
14
  factory :user_with_addresses, aliases: [:user_with_addreses] do
24
15
  after(:create) do |user|
25
16
  user.ship_address = create(:address, user: user)
@@ -30,4 +21,15 @@ FactoryBot.define do
30
21
  end
31
22
  end
32
23
  end
24
+
25
+ factory :admin_user, class: Spree.admin_user_class do
26
+ email { generate(:random_email) }
27
+ login { email }
28
+ password { 'secret' }
29
+ password_confirmation { password }
30
+ first_name { FFaker::Name.first_name }
31
+ last_name { FFaker::Name.last_name }
32
+
33
+ spree_roles { [Spree::Role.find_by(name: 'admin') || create(:role, name: 'admin')] }
34
+ end
33
35
  end
@@ -12,23 +12,41 @@ FactoryBot.define do
12
12
  is_master { 0 }
13
13
  track_inventory { true }
14
14
 
15
- product { |p| p.association(:base_product, stores: [create(:store)]) }
15
+ product { |p| p.association(:base_product, stores: [Spree::Store.default]) }
16
16
  option_values { [create(:option_value)] }
17
17
 
18
+ transient do
19
+ create_stock { true }
20
+ end
21
+
18
22
  # ensure stock item will be created for this variant
19
- before(:create) { create(:stock_location) unless Spree::StockLocation.any? }
23
+ before(:create) do |variant, evaluator|
24
+ create(:stock_location) if evaluator.create_stock && !Spree::StockLocation.any?
25
+ end
26
+
27
+ after(:create) do |variant, evaluator|
28
+ if evaluator.create_stock
29
+ Spree::StockLocation.all.each do |stock_location|
30
+ next if stock_location.stock_item(variant).present?
20
31
 
21
- after(:create) do |variant|
22
- Spree::StockLocation.all.each { |stock_location| stock_location.propagate_variant(variant) }
32
+ stock_location.propagate_variant(variant)
33
+ end
34
+ end
23
35
  end
24
36
 
25
37
  factory :variant do
26
38
  # on_hand 5
27
- product { |p| p.association(:product, stores: [create(:store)]) }
39
+ product { |p| p.association(:product, stores: [Spree::Store.default]) }
28
40
 
29
41
  factory :with_image_variant do
30
42
  images { create_list(:image, 1) }
31
43
  end
44
+
45
+ trait :with_no_price do
46
+ price { nil }
47
+ cost_price { nil }
48
+ currency { nil }
49
+ end
32
50
  end
33
51
 
34
52
  factory :master_variant do
@@ -1,9 +1,3 @@
1
1
  RSpec.configure do |config|
2
- config.before(:each, :job) do
3
- ActiveJob::Base.queue_adapter = :test
4
- end
5
-
6
- config.after(:each, :job) do
7
- ActiveJob::Base.queue_adapter = :inline
8
- end
2
+ config.include ActiveJob::TestHelper
9
3
  end
@@ -38,7 +38,7 @@ shared_examples_for 'metadata' do |factory: described_class.name.demodulize.unde
38
38
  expect(subject.public_metadata['additional_data']).to eq(hash.stringify_keys)
39
39
  end
40
40
 
41
- it 'can query records by metadata properties', skip: ENV['DB'] == 'mysql' do
41
+ it 'can query records by metadata properties', skip: (ENV['DB'].blank? || ENV['DB'] == 'mysql') do
42
42
  subject.public_metadata[:color] = 'red'
43
43
  subject.public_metadata[:priority] = 1
44
44
  subject.public_metadata[:keywords] = ['k1', 'k2']
@@ -51,4 +51,16 @@ shared_examples_for 'metadata' do |factory: described_class.name.demodulize.unde
51
51
  expect(described_class.where("public_metadata -> 'keywords' ? :keyword", keyword: 'k1').count).to eq(1)
52
52
  expect(described_class.where("public_metadata -> 'additional_data' ->> 'size' = :size", size: 'big').count).to eq(1)
53
53
  end
54
+
55
+ it 'can query records by metadata properties', skip: ENV['DB'] == 'postgres' do
56
+ subject.public_metadata[:color] = 'red'
57
+ subject.public_metadata[:priority] = 1
58
+ subject.public_metadata[:additional_data] = { size: 'big', material: 'wool' }
59
+
60
+ subject.save!
61
+
62
+ expect(described_class.where("JSON_EXTRACT(public_metadata, '$.color') = ?", 'red').count).to eq(1)
63
+ expect(described_class.where("JSON_EXTRACT(public_metadata, '$.priority') = 1").count).to eq(1)
64
+ expect(described_class.where("JSON_EXTRACT(public_metadata, '$.additional_data.size') = :size", size: 'big').count).to eq(1)
65
+ end
54
66
  end
@@ -1,12 +1,6 @@
1
1
  class OrderWalkthrough
2
2
  def self.up_to(state, store = nil)
3
- store ||= if Spree::Store.exists?
4
- # Ensure the default store is used
5
- Spree::Store.default || FactoryBot.create(:store, default: true)
6
- else
7
- # Create a default store
8
- FactoryBot.create(:store, default: true)
9
- end
3
+ store ||= Spree::Store.default
10
4
 
11
5
  # A payment method must exist for an order to proceed through the Address state
12
6
  unless Spree::PaymentMethod.exists?
@@ -9,10 +9,7 @@ module Spree
9
9
  # end
10
10
  #
11
11
  def reset_spree_preferences(&config_block)
12
- Spree::Preferences::Store.instance.persistence = false
13
- Spree::Preferences::Store.instance.clear_cache
14
-
15
- config = Rails.application.config.spree.preferences
12
+ config = Rails.application.config.spree.preferences.reset
16
13
  configure_spree_preferences &config_block if block_given?
17
14
  end
18
15
 
@@ -0,0 +1,26 @@
1
+ # setup default store, to be always present
2
+ RSpec.configure do |config|
3
+ config.before(:all) do
4
+ unless self.class.metadata[:without_global_store]
5
+ @default_country = Spree::Country.find_by(iso: 'US') || FactoryBot.create(:country_us)
6
+ @default_store = Spree::Store.find_by(default: true) || FactoryBot.create(:store, default: true, default_country: @default_country, default_currency: 'USD')
7
+ end
8
+ end
9
+
10
+ config.after(:each) do
11
+ unless self.class.metadata[:without_global_store]
12
+ @default_store&.products = []
13
+ @default_store&.promotions = []
14
+ @default_store&.checkout_zone = nil
15
+ @default_store&.payment_methods = []
16
+ end
17
+ end
18
+
19
+ config.after(:all) do
20
+ unless self.class.metadata[:without_global_store]
21
+ DatabaseCleaner.strategy = :transaction
22
+ DatabaseCleaner.clean_with(:truncation)
23
+ clear_enqueued_jobs
24
+ end
25
+ end
26
+ end
data/lib/spree_core.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'friendly_id/paranoia'
2
2
  require 'mobility/plugins/store_based_fallbacks'
3
+ require 'normalize_string'
3
4
 
4
5
  require 'spree/core'
@@ -0,0 +1,4 @@
1
+ // @rails/request.js@0.0.8 downloaded from https://ga.jspm.io/npm:@rails/request.js@0.0.8/src/index.js
2
+
3
+ class FetchResponse{constructor(t){this.response=t}get statusCode(){return this.response.status}get redirected(){return this.response.redirected}get ok(){return this.response.ok}get unauthenticated(){return 401===this.statusCode}get unprocessableEntity(){return 422===this.statusCode}get authenticationURL(){return this.response.headers.get("WWW-Authenticate")}get contentType(){const t=this.response.headers.get("Content-Type")||"";return t.replace(/;.*$/,"")}get headers(){return this.response.headers}get html(){return this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)?this.text:Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`))}get json(){return this.contentType.match(/^application\/.*json$/)?this.responseJson||(this.responseJson=this.response.json()):Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`))}get text(){return this.responseText||(this.responseText=this.response.text())}get isTurboStream(){return this.contentType.match(/^text\/vnd\.turbo-stream\.html/)}async renderTurboStream(){if(!this.isTurboStream)return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`));window.Turbo?await window.Turbo.renderStreamMessage(await this.text):console.warn("You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js")}}class RequestInterceptor{static register(t){this.interceptor=t}static get(){return this.interceptor}static reset(){this.interceptor=void 0}}function getCookie(t){const e=document.cookie?document.cookie.split("; "):[];const n=`${encodeURIComponent(t)}=`;const s=e.find((t=>t.startsWith(n)));if(s){const t=s.split("=").slice(1).join("=");if(t)return decodeURIComponent(t)}}function compact(t){const e={};for(const n in t){const s=t[n];void 0!==s&&(e[n]=s)}return e}function metaContent(t){const e=document.head.querySelector(`meta[name="${t}"]`);return e&&e.content}function stringEntriesFromFormData(t){return[...t].reduce(((t,[e,n])=>t.concat("string"===typeof n?[[e,n]]:[])),[])}function mergeEntries(t,e){for(const[n,s]of e)if(!(s instanceof window.File))if(t.has(n)&&!n.includes("[]")){t.delete(n);t.set(n,s)}else t.append(n,s)}class FetchRequest{constructor(t,e,n={}){this.method=t;this.options=n;this.originalUrl=e.toString()}async perform(){try{const t=RequestInterceptor.get();t&&await t(this)}catch(t){console.error(t)}const t=new FetchResponse(await window.fetch(this.url,this.fetchOptions));if(t.unauthenticated&&t.authenticationURL)return Promise.reject(window.location.href=t.authenticationURL);t.ok&&t.isTurboStream&&await t.renderTurboStream();return t}addHeader(t,e){const n=this.additionalHeaders;n[t]=e;this.options.headers=n}sameHostname(){if(!this.originalUrl.startsWith("http:"))return true;try{return new URL(this.originalUrl).hostname===window.location.hostname}catch(t){return true}}get fetchOptions(){return{method:this.method.toUpperCase(),headers:this.headers,body:this.formattedBody,signal:this.signal,credentials:"same-origin",redirect:this.redirect}}get headers(){const t={"X-Requested-With":"XMLHttpRequest","Content-Type":this.contentType,Accept:this.accept};this.sameHostname()&&(t["X-CSRF-Token"]=this.csrfToken);return compact(Object.assign(t,this.additionalHeaders))}get csrfToken(){return getCookie(metaContent("csrf-param"))||metaContent("csrf-token")}get contentType(){return this.options.contentType?this.options.contentType:null==this.body||this.body instanceof window.FormData?void 0:this.body instanceof window.File?this.body.type:"application/json"}get accept(){switch(this.responseKind){case"html":return"text/html, application/xhtml+xml";case"turbo-stream":return"text/vnd.turbo-stream.html, text/html, application/xhtml+xml";case"json":return"application/json, application/vnd.api+json";default:return"*/*"}}get body(){return this.options.body}get query(){const t=(this.originalUrl.split("?")[1]||"").split("#")[0];const e=new URLSearchParams(t);let n=this.options.query;n=n instanceof window.FormData?stringEntriesFromFormData(n):n instanceof window.URLSearchParams?n.entries():Object.entries(n||{});mergeEntries(e,n);const s=e.toString();return s.length>0?`?${s}`:""}get url(){return this.originalUrl.split("?")[0].split("#")[0]+this.query}get responseKind(){return this.options.responseKind||"html"}get signal(){return this.options.signal}get redirect(){return this.options.redirect||"follow"}get additionalHeaders(){return this.options.headers||{}}get formattedBody(){const t="[object String]"===Object.prototype.toString.call(this.body);const e="application/json"===this.headers["Content-Type"];return e&&!t?JSON.stringify(this.body):this.body}}async function get(t,e){const n=new FetchRequest("get",t,e);return n.perform()}async function post(t,e){const n=new FetchRequest("post",t,e);return n.perform()}async function put(t,e){const n=new FetchRequest("put",t,e);return n.perform()}async function patch(t,e){const n=new FetchRequest("patch",t,e);return n.perform()}async function destroy(t,e){const n=new FetchRequest("delete",t,e);return n.perform()}export{FetchRequest,FetchResponse,RequestInterceptor,destroy,get,patch,post,put};
4
+
@@ -0,0 +1,4 @@
1
+ // @stimulus-components/auto-submit@6.0.0 downloaded from https://ga.jspm.io/npm:@stimulus-components/auto-submit@6.0.0/dist/stimulus-auto-submit.mjs
2
+
3
+ import{Controller as t}from"@hotwired/stimulus";function debounce(t,e){let i;return(...s)=>{clearTimeout(i),i=setTimeout((()=>{t.apply(this,s)}),e)}}const e=class _AutoSubmit extends t{initialize(){this.submit=this.submit.bind(this)}connect(){this.delayValue>0&&(this.submit=debounce(this.submit,this.delayValue))}submit(){this.element.requestSubmit()}};e.values={delay:{type:Number,default:150}};let i=e;export{i as default};
4
+
@@ -0,0 +1,4 @@
1
+ // stimulus-reveal-controller@4.1.0 downloaded from https://ga.jspm.io/npm:stimulus-reveal-controller@4.1.0/dist/stimulus-reveal-controller.mjs
2
+
3
+ import{Controller as s}from"@hotwired/stimulus";class t extends s{connect(){this.class=this.hasHiddenClass?this.hiddenClass:"hidden"}toggle(){this.itemTargets.forEach((s=>{s.classList.toggle(this.class)}))}show(){this.itemTargets.forEach((s=>{s.classList.remove(this.class)}))}hide(){this.itemTargets.forEach((s=>{s.classList.add(this.class)}))}}t.targets=["item"];t.classes=["hidden"];export{t as default};
4
+
@@ -0,0 +1,4 @@
1
+ // tailwindcss-stimulus-components@3.0.4 downloaded from https://ga.jspm.io/npm:tailwindcss-stimulus-components@3.0.4/dist/tailwindcss-stimulus-components.modern.js
2
+
3
+ import{Controller as t}from"@hotwired/stimulus";class s extends t{initialize(){this.hide()}connect(){setTimeout((()=>{this.show()}),this.showDelayValue),this.hasDismissAfterValue&&setTimeout((()=>{this.close()}),this.dismissAfterValue)}close(){this.hide(),setTimeout((()=>{this.element.remove()}),this.removeDelayValue)}show(){this.element.classList.add(...this.showClasses),this.element.classList.remove(...this.hideClasses)}hide(){this.element.classList.add(...this.hideClasses),this.element.classList.remove(...this.showClasses)}}s.values={dismissAfter:Number,showDelay:{type:Number,default:200},removeDelay:{type:Number,default:1100}},s.classes=["show","hide"];class e extends t{connect(){this.timeout=null,this.duration=this.data.get("duration")||1e3}save(){clearTimeout(this.timeout),this.timeout=setTimeout((()=>{this.statusTarget.textContent="Saving...",Rails.fire(this.formTarget,"submit")}),this.duration)}success(){this.setStatus("Saved!")}error(){this.setStatus("Unable to save!")}setStatus(t){this.statusTarget.textContent=t,this.timeout=setTimeout((()=>{this.statusTarget.textContent=""}),2e3)}}e.targets=["form","status"];class i extends t{constructor(...t){super(...t),this._onMenuButtonKeydown=t=>{switch(t.keyCode){case 13:case 32:t.preventDefault(),this.toggle()}}}connect(){this.toggleClass=this.data.get("class")||"hidden",this.visibleClass=this.data.get("visibleClass")||null,this.invisibleClass=this.data.get("invisibleClass")||null,this.activeClass=this.data.get("activeClass")||null,this.enteringClass=this.data.get("enteringClass")||null,this.leavingClass=this.data.get("leavingClass")||null,this.hasButtonTarget&&this.buttonTarget.addEventListener("keydown",this._onMenuButtonKeydown),this.element.setAttribute("aria-haspopup","true")}disconnect(){this.hasButtonTarget&&this.buttonTarget.removeEventListener("keydown",this._onMenuButtonKeydown)}toggle(){this.openValue=!this.openValue}openValueChanged(){this.openValue?this._show():this._hide()}_show(t){setTimeout((()=>{this.menuTarget.classList.remove(this.toggleClass),this.element.setAttribute("aria-expanded","true"),this._enteringClassList[0].forEach((t=>{this.menuTarget.classList.add(t)}).bind(this)),this._activeClassList[0].forEach((t=>{this.activeTarget.classList.add(t)})),this._invisibleClassList[0].forEach((t=>this.menuTarget.classList.remove(t))),this._visibleClassList[0].forEach((t=>{this.menuTarget.classList.add(t)})),setTimeout((()=>{this._enteringClassList[0].forEach((t=>this.menuTarget.classList.remove(t)))}).bind(this),this.enterTimeout[0]),"function"==typeof t&&t()}).bind(this))}_hide(t){setTimeout((()=>{this.element.setAttribute("aria-expanded","false"),this._invisibleClassList[0].forEach((t=>this.menuTarget.classList.add(t))),this._visibleClassList[0].forEach((t=>this.menuTarget.classList.remove(t))),this._activeClassList[0].forEach((t=>this.activeTarget.classList.remove(t))),this._leavingClassList[0].forEach((t=>this.menuTarget.classList.add(t))),setTimeout((()=>{this._leavingClassList[0].forEach((t=>this.menuTarget.classList.remove(t))),"function"==typeof t&&t(),this.menuTarget.classList.add(this.toggleClass)}).bind(this),this.leaveTimeout[0])}).bind(this))}show(){this.openValue=!0}hide(t){!1===this.element.contains(t.target)&&this.openValue&&(this.openValue=!1)}get activeTarget(){return this.data.has("activeTarget")?document.querySelector(this.data.get("activeTarget")):this.element}get _activeClassList(){return this.activeClass?this.activeClass.split(",").map((t=>t.split(" "))):[[],[]]}get _visibleClassList(){return this.visibleClass?this.visibleClass.split(",").map((t=>t.split(" "))):[[],[]]}get _invisibleClassList(){return this.invisibleClass?this.invisibleClass.split(",").map((t=>t.split(" "))):[[],[]]}get _enteringClassList(){return this.enteringClass?this.enteringClass.split(",").map((t=>t.split(" "))):[[],[]]}get _leavingClassList(){return this.leavingClass?this.leavingClass.split(",").map((t=>t.split(" "))):[[],[]]}get enterTimeout(){return(this.data.get("enterTimeout")||"0,0").split(",").map((t=>parseInt(t)))}get leaveTimeout(){return(this.data.get("leaveTimeout")||"0,0").split(",").map((t=>parseInt(t)))}}i.targets=["menu","button"],i.values={open:Boolean};class a extends t{connect(){this.toggleClass=this.data.get("class")||"hidden",this.backgroundId=this.data.get("backgroundId")||"modal-background",this.backgroundHtml=this.data.get("backgroundHtml")||this._backgroundHTML(),this.allowBackgroundClose="true"===(this.data.get("allowBackgroundClose")||"true"),this.preventDefaultActionOpening="true"===(this.data.get("preventDefaultActionOpening")||"true"),this.preventDefaultActionClosing="true"===(this.data.get("preventDefaultActionClosing")||"true")}disconnect(){this.close()}open(t){this.preventDefaultActionOpening&&t.preventDefault(),t.target.blur&&t.target.blur(),this.lockScroll(),this.containerTarget.classList.remove(this.toggleClass),this.data.get("disable-backdrop")||(document.body.insertAdjacentHTML("beforeend",this.backgroundHtml),this.background=document.querySelector(`#${this.backgroundId}`))}close(t){t&&this.preventDefaultActionClosing&&t.preventDefault(),this.unlockScroll(),this.containerTarget.classList.add(this.toggleClass),this.background&&this.background.remove()}closeBackground(t){this.allowBackgroundClose&&t.target===this.containerTarget&&this.close(t)}closeWithKeyboard(t){27!==t.keyCode||this.containerTarget.classList.contains(this.toggleClass)||this.close(t)}_backgroundHTML(){return`<div id="${this.backgroundId}" class="fixed top-0 left-0 w-full h-full" style="background-color: ${this.backdropColorValue}; z-index: 9998;"></div>`}lockScroll(){const t=window.innerWidth-document.documentElement.clientWidth;document.body.style.paddingRight=`${t}px`,this.saveScrollPosition(),document.body.classList.add("fixed","inset-x-0","overflow-hidden"),document.body.style.top=`-${this.scrollPosition}px`}unlockScroll(){document.body.style.paddingRight=null,document.body.classList.remove("fixed","inset-x-0","overflow-hidden"),this.restoreScrollValue&&this.restoreScrollPosition(),document.body.style.top=null}saveScrollPosition(){this.scrollPosition=window.pageYOffset||document.body.scrollTop}restoreScrollPosition(){void 0!==this.scrollPosition&&(document.documentElement.scrollTop=this.scrollPosition)}}a.targets=["container"],a.values={backdropColor:{type:String,default:"rgba(0, 0, 0, 0.8)"},restoreScroll:{type:Boolean,default:!0}};class l extends t{connect(){this.activeTabClasses=(this.data.get("activeTab")||"active").split(" "),this.inactiveTabClasses=(this.data.get("inactiveTab")||"inactive").split(" "),this.anchor&&(this.index=this.tabTargets.findIndex((t=>t.id===this.anchor))),this.showTab()}change(t){t.preventDefault(),this.index=t.currentTarget.dataset.index?t.currentTarget.dataset.index:t.currentTarget.dataset.id?this.tabTargets.findIndex((d=>d.id==t.currentTarget.dataset.id)):this.tabTargets.indexOf(t.currentTarget),window.dispatchEvent(new CustomEvent("tsc:tab-change"))}showTab(){this.tabTargets.forEach(((t,d)=>{const c=this.panelTargets[d];d===this.index?(c.classList.remove("hidden"),t.classList.remove(...this.inactiveTabClasses),t.classList.add(...this.activeTabClasses),t.id&&(location.hash=t.id)):(c.classList.add("hidden"),t.classList.remove(...this.activeTabClasses),t.classList.add(...this.inactiveTabClasses))}))}get index(){return parseInt(this.data.get("index")||0)}set index(t){this.data.set("index",t>=0?t:0),this.showTab()}get anchor(){return document.URL.split("#").length>1?document.URL.split("#")[1]:null}}l.targets=["tab","panel"];class o extends t{connect(){this.toggleClass=this.data.get("class")||"hidden"}toggle(t){t.preventDefault(),this.openValue=!this.openValue}hide(t){t.preventDefault(),this.openValue=!1}show(t){t.preventDefault(),this.openValue=!0}openValueChanged(){this.toggleClass&&this.toggleableTargets.forEach((t=>{t.classList.toggle(this.toggleClass)}))}}o.targets=["toggleable"],o.values={open:Boolean};class n extends t{initialize(){this.contentTarget.setAttribute("style",`transform:translate(${this.data.get("translateX")}, ${this.data.get("translateY")});`)}mouseOver(){this.contentTarget.classList.remove("hidden")}mouseOut(){this.contentTarget.classList.add("hidden")}toggle(){this.contentTarget.classList.contains("hidden")?this.contentTarget.classList.remove("hidden"):this.contentTarget.classList.add("hidden")}}n.targets=["content"];class r extends i{_show(){this.overlayTarget.classList.remove(this.toggleClass),super._show((()=>{this._activeClassList[1].forEach((t=>this.overlayTarget.classList.add(t))),this._invisibleClassList[1].forEach((t=>this.overlayTarget.classList.remove(t))),this._visibleClassList[1].forEach((t=>this.overlayTarget.classList.add(t))),setTimeout((()=>{this._enteringClassList[1].forEach((t=>this.overlayTarget.classList.remove(t)))}).bind(this),this.enterTimeout[1])}).bind(this))}_hide(){this._leavingClassList[1].forEach((t=>this.overlayTarget.classList.add(t))),super._hide((()=>{setTimeout((()=>{this._visibleClassList[1].forEach((t=>this.overlayTarget.classList.remove(t))),this._invisibleClassList[1].forEach((t=>this.overlayTarget.classList.add(t))),this._activeClassList[1].forEach((t=>this.overlayTarget.classList.remove(t))),this._leavingClassList[1].forEach((t=>this.overlayTarget.classList.remove(t))),this.overlayTarget.classList.add(this.toggleClass)}).bind(this),this.leaveTimeout[1])}).bind(this))}}r.targets=["menu","overlay"];class h extends t{connect(){this.styleProperty=this.data.get("style")||"backgroundColor"}update(){this.preview=this.color}set preview(t){this.previewTarget.style[this.styleProperty]=t;const d=this._getContrastYIQ(t);"color"===this.styleProperty?this.previewTarget.style.backgroundColor=d:this.previewTarget.style.color=d}get color(){return this.colorTarget.value}_getContrastYIQ(t){return t=t.replace("#",""),(299*parseInt(t.substr(0,2),16)+587*parseInt(t.substr(2,2),16)+114*parseInt(t.substr(4,2),16))/1e3>=128?"#000":"#fff"}}h.targets=["preview","color"];export{s as Alert,e as Autosave,h as ColorPreview,i as Dropdown,a as Modal,n as Popover,r as Slideover,l as Tabs,o as Toggle};
4
+