solidus_admin 0.4.0 → 0.5.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 (335) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +23 -4
  3. data/README.md +6 -1
  4. data/Rakefile +15 -15
  5. data/app/assets/builds/solidus_admin/tailwind.css +722 -45
  6. data/app/assets/images/solidus_admin/remixicon.license.txt +196 -0
  7. data/app/assets/images/solidus_admin/remixicon.symbol.svg +4 -4
  8. data/app/blueprints/solidus_admin/state_blueprint.rb +13 -0
  9. data/app/components/concerns/solidus_admin/slotable_default.rb +42 -0
  10. data/app/components/solidus_admin/adjustment_reasons/edit/component.html.erb +6 -15
  11. data/app/components/solidus_admin/adjustment_reasons/edit/component.yml +0 -1
  12. data/app/components/solidus_admin/adjustment_reasons/index/component.rb +13 -13
  13. data/app/components/solidus_admin/adjustment_reasons/new/component.html.erb +6 -15
  14. data/app/components/solidus_admin/adjustment_reasons/new/component.yml +0 -1
  15. data/app/components/solidus_admin/base_component.rb +7 -3
  16. data/app/components/solidus_admin/layout/confirm/component.html.erb +18 -0
  17. data/app/components/solidus_admin/layout/confirm/component.js +21 -0
  18. data/app/components/solidus_admin/layout/confirm/component.rb +26 -0
  19. data/app/components/solidus_admin/layout/confirm/component.yml +4 -0
  20. data/app/components/solidus_admin/layout/flashes/alerts/component.html.erb +7 -0
  21. data/app/components/solidus_admin/layout/flashes/alerts/component.rb +19 -0
  22. data/app/components/solidus_admin/layout/flashes/component.html.erb +5 -0
  23. data/app/components/solidus_admin/layout/flashes/component.rb +4 -0
  24. data/app/components/solidus_admin/layout/flashes/toasts/component.html.erb +5 -0
  25. data/app/components/solidus_admin/layout/flashes/toasts/component.rb +9 -0
  26. data/app/components/solidus_admin/layout/navigation/account/component.html.erb +12 -1
  27. data/app/components/solidus_admin/layout/navigation/account/component.rb +4 -4
  28. data/app/components/solidus_admin/layout/page_helpers.rb +3 -9
  29. data/app/components/solidus_admin/layout/skip_link/component.rb +3 -3
  30. data/app/components/solidus_admin/option_types/edit/component.html.erb +44 -0
  31. data/app/components/solidus_admin/option_types/edit/component.rb +5 -0
  32. data/app/components/solidus_admin/option_types/edit/component.yml +10 -0
  33. data/app/components/solidus_admin/option_types/index/component.rb +22 -22
  34. data/app/components/solidus_admin/option_types/new/component.html.erb +16 -0
  35. data/app/components/solidus_admin/option_types/new/component.rb +4 -0
  36. data/app/components/solidus_admin/option_types/new/component.yml +4 -0
  37. data/app/components/solidus_admin/option_values/edit/component.html.erb +16 -0
  38. data/app/components/solidus_admin/option_values/edit/component.rb +4 -0
  39. data/app/components/solidus_admin/option_values/edit/component.yml +4 -0
  40. data/app/components/solidus_admin/option_values/new/component.html.erb +16 -0
  41. data/app/components/solidus_admin/option_values/new/component.rb +7 -0
  42. data/app/components/solidus_admin/option_values/new/component.yml +4 -0
  43. data/app/components/solidus_admin/option_values/table/component.rb +53 -0
  44. data/app/components/solidus_admin/option_values/table/component.yml +3 -0
  45. data/app/components/solidus_admin/orders/cart/component.html.erb +5 -7
  46. data/app/components/solidus_admin/orders/cart/result/component.html.erb +2 -2
  47. data/app/components/solidus_admin/orders/index/component.rb +26 -26
  48. data/app/components/solidus_admin/orders/show/address/component.html.erb +8 -20
  49. data/app/components/solidus_admin/orders/show/address/component.rb +7 -7
  50. data/app/components/solidus_admin/orders/show/address/component.yml +0 -1
  51. data/app/components/solidus_admin/orders/show/adjustments/index/adjustable/spree_shipment/component.rb +1 -1
  52. data/app/components/solidus_admin/orders/show/adjustments/index/component.rb +24 -21
  53. data/app/components/solidus_admin/orders/show/component.html.erb +2 -2
  54. data/app/components/solidus_admin/orders/show/component.rb +1 -1
  55. data/app/components/solidus_admin/orders/show/component.yml +0 -3
  56. data/app/components/solidus_admin/orders/show/customer_search/result/component.html.erb +2 -2
  57. data/app/components/solidus_admin/orders/show/email/component.html.erb +2 -2
  58. data/app/components/solidus_admin/payment_methods/edit/component.html.erb +13 -0
  59. data/app/components/solidus_admin/payment_methods/edit/component.rb +7 -0
  60. data/app/components/solidus_admin/payment_methods/edit/component.yml +2 -0
  61. data/app/components/solidus_admin/payment_methods/form/component.html.erb +29 -0
  62. data/app/components/solidus_admin/payment_methods/form/component.rb +34 -0
  63. data/app/components/solidus_admin/payment_methods/form/component.yml +15 -0
  64. data/app/components/solidus_admin/payment_methods/index/component.rb +24 -23
  65. data/app/components/solidus_admin/payment_methods/new/component.html.erb +12 -0
  66. data/app/components/solidus_admin/payment_methods/new/component.rb +7 -0
  67. data/app/components/solidus_admin/payment_methods/new/component.yml +2 -0
  68. data/app/components/solidus_admin/products/index/component.rb +26 -26
  69. data/app/components/solidus_admin/products/show/categories/new/component.html.erb +17 -0
  70. data/app/components/solidus_admin/products/show/categories/new/component.rb +17 -0
  71. data/app/components/solidus_admin/products/show/categories/new/component.yml +5 -0
  72. data/app/components/solidus_admin/products/show/component.html.erb +90 -66
  73. data/app/components/solidus_admin/products/show/component.rb +2 -2
  74. data/app/components/solidus_admin/products/show/component.yml +23 -11
  75. data/app/components/solidus_admin/products/status/component.rb +1 -1
  76. data/app/components/solidus_admin/products/stock/component.rb +7 -7
  77. data/app/components/solidus_admin/properties/edit/component.html.erb +5 -5
  78. data/app/components/solidus_admin/properties/index/component.rb +13 -13
  79. data/app/components/solidus_admin/properties/new/component.html.erb +5 -5
  80. data/app/components/solidus_admin/refund_reasons/edit/component.html.erb +6 -15
  81. data/app/components/solidus_admin/refund_reasons/edit/component.yml +0 -1
  82. data/app/components/solidus_admin/refund_reasons/index/component.rb +13 -13
  83. data/app/components/solidus_admin/refund_reasons/new/component.html.erb +6 -14
  84. data/app/components/solidus_admin/refund_reasons/new/component.yml +0 -1
  85. data/app/components/solidus_admin/refunds_and_returns/component.rb +7 -7
  86. data/app/components/solidus_admin/reimbursement_types/index/component.rb +2 -2
  87. data/app/components/solidus_admin/return_reasons/edit/component.html.erb +5 -14
  88. data/app/components/solidus_admin/return_reasons/index/component.rb +11 -11
  89. data/app/components/solidus_admin/return_reasons/new/component.html.erb +5 -14
  90. data/app/components/solidus_admin/roles/edit/component.html.erb +12 -12
  91. data/app/components/solidus_admin/roles/edit/component.yml +0 -1
  92. data/app/components/solidus_admin/roles/index/component.rb +12 -12
  93. data/app/components/solidus_admin/roles/new/component.html.erb +12 -12
  94. data/app/components/solidus_admin/roles/new/component.yml +0 -1
  95. data/app/components/solidus_admin/shipping/component.rb +5 -5
  96. data/app/components/solidus_admin/shipping_categories/edit/component.html.erb +4 -4
  97. data/app/components/solidus_admin/shipping_categories/edit/component.yml +0 -1
  98. data/app/components/solidus_admin/shipping_categories/index/component.rb +9 -9
  99. data/app/components/solidus_admin/shipping_categories/new/component.html.erb +4 -4
  100. data/app/components/solidus_admin/shipping_categories/new/component.yml +0 -1
  101. data/app/components/solidus_admin/shipping_methods/index/component.rb +10 -10
  102. data/app/components/solidus_admin/stock_items/edit/component.html.erb +5 -8
  103. data/app/components/solidus_admin/stock_items/edit/component.rb +2 -2
  104. data/app/components/solidus_admin/stock_items/index/component.rb +25 -25
  105. data/app/components/solidus_admin/stock_locations/edit/component.html.erb +16 -0
  106. data/app/components/solidus_admin/stock_locations/edit/component.rb +5 -0
  107. data/app/components/solidus_admin/stock_locations/edit/component.yml +2 -0
  108. data/app/components/solidus_admin/stock_locations/form/component.html.erb +65 -0
  109. data/app/components/solidus_admin/stock_locations/form/component.rb +11 -0
  110. data/app/components/solidus_admin/stock_locations/form/component.yml +19 -0
  111. data/app/components/solidus_admin/stock_locations/index/component.rb +94 -47
  112. data/app/components/solidus_admin/stock_locations/new/component.html.erb +16 -0
  113. data/app/components/solidus_admin/stock_locations/new/component.rb +16 -0
  114. data/app/components/solidus_admin/stock_locations/new/component.yml +2 -0
  115. data/app/components/solidus_admin/store_credit_reasons/edit/component.html.erb +5 -14
  116. data/app/components/solidus_admin/store_credit_reasons/edit/component.yml +0 -1
  117. data/app/components/solidus_admin/store_credit_reasons/index/component.rb +11 -11
  118. data/app/components/solidus_admin/store_credit_reasons/new/component.html.erb +5 -14
  119. data/app/components/solidus_admin/store_credit_reasons/new/component.yml +0 -1
  120. data/app/components/solidus_admin/stores/edit/component.html.erb +27 -0
  121. data/app/components/solidus_admin/stores/edit/component.rb +5 -0
  122. data/app/components/solidus_admin/stores/form/component.html.erb +102 -0
  123. data/app/components/solidus_admin/stores/form/component.rb +27 -0
  124. data/app/components/solidus_admin/stores/form/component.yml +17 -0
  125. data/app/components/solidus_admin/stores/index/component.rb +51 -22
  126. data/app/components/solidus_admin/stores/new/component.html.erb +16 -0
  127. data/app/components/solidus_admin/stores/new/component.rb +5 -0
  128. data/app/components/solidus_admin/stores/new/component.yml +2 -0
  129. data/app/components/solidus_admin/tax_categories/edit/component.html.erb +7 -15
  130. data/app/components/solidus_admin/tax_categories/edit/component.yml +0 -1
  131. data/app/components/solidus_admin/tax_categories/index/component.rb +17 -17
  132. data/app/components/solidus_admin/tax_categories/new/component.html.erb +7 -15
  133. data/app/components/solidus_admin/tax_categories/new/component.yml +0 -1
  134. data/app/components/solidus_admin/tax_rates/edit/component.html.erb +12 -0
  135. data/app/components/solidus_admin/tax_rates/edit/component.rb +5 -0
  136. data/app/components/solidus_admin/tax_rates/edit/component.yml +4 -0
  137. data/app/components/solidus_admin/tax_rates/form/component.html.erb +25 -0
  138. data/app/components/solidus_admin/tax_rates/form/component.rb +29 -0
  139. data/app/components/solidus_admin/tax_rates/form/component.yml +9 -0
  140. data/app/components/solidus_admin/tax_rates/index/component.rb +38 -20
  141. data/app/components/solidus_admin/tax_rates/new/component.html.erb +12 -0
  142. data/app/components/solidus_admin/tax_rates/new/component.rb +5 -0
  143. data/app/components/solidus_admin/tax_rates/new/component.yml +4 -0
  144. data/app/components/solidus_admin/taxes/component.rb +4 -4
  145. data/app/components/solidus_admin/taxonomies/index/component.rb +7 -7
  146. data/app/components/solidus_admin/turbo/target_frame/component.html.erb +5 -0
  147. data/app/components/solidus_admin/turbo/target_frame/component.rb +8 -0
  148. data/app/components/solidus_admin/ui/alert/component.html.erb +35 -0
  149. data/app/components/solidus_admin/ui/alert/component.rb +51 -0
  150. data/app/components/solidus_admin/ui/alert/component.yml +8 -0
  151. data/app/components/solidus_admin/ui/badge/component.rb +11 -11
  152. data/app/components/solidus_admin/ui/button/component.rb +84 -27
  153. data/app/components/solidus_admin/ui/button/component.yml +10 -0
  154. data/app/components/solidus_admin/ui/checkbox/component.rb +42 -0
  155. data/app/components/solidus_admin/ui/dropdown/component.rb +3 -3
  156. data/app/components/solidus_admin/ui/forms/address/component.html.erb +1 -48
  157. data/app/components/solidus_admin/ui/forms/address/component.rb +29 -6
  158. data/app/components/solidus_admin/ui/forms/address/fields/city_and_zipcode/component.html.erb +4 -0
  159. data/app/components/solidus_admin/ui/forms/address/fields/city_and_zipcode/component.rb +8 -0
  160. data/app/components/solidus_admin/ui/forms/address/fields/country_and_state/component.html.erb +39 -0
  161. data/app/components/solidus_admin/ui/forms/address/{component.js → fields/country_and_state/component.js} +2 -0
  162. data/app/components/solidus_admin/ui/forms/address/fields/country_and_state/component.rb +15 -0
  163. data/app/components/solidus_admin/ui/forms/address/fields/reverse_charge_fields/component.html.erb +7 -0
  164. data/app/components/solidus_admin/ui/forms/address/fields/reverse_charge_fields/component.rb +12 -0
  165. data/app/components/solidus_admin/ui/forms/address/fieldsets/base.rb +54 -0
  166. data/app/components/solidus_admin/ui/forms/address/fieldsets/contact/component.rb +16 -0
  167. data/app/components/solidus_admin/ui/forms/address/fieldsets/contact_info/component.rb +10 -0
  168. data/app/components/solidus_admin/ui/forms/address/fieldsets/location/component.rb +14 -0
  169. data/app/components/solidus_admin/ui/forms/checkbox/component.html.erb +14 -0
  170. data/app/components/solidus_admin/ui/forms/checkbox/component.rb +24 -31
  171. data/app/components/solidus_admin/ui/forms/field/component.html.erb +4 -4
  172. data/app/components/solidus_admin/ui/forms/field/component.rb +14 -18
  173. data/app/components/solidus_admin/ui/forms/input/component.rb +9 -18
  174. data/app/components/solidus_admin/ui/forms/search/result/component.rb +2 -2
  175. data/app/components/solidus_admin/ui/forms/select/component.html.erb +21 -0
  176. data/app/components/solidus_admin/ui/forms/select/component.rb +157 -0
  177. data/app/components/solidus_admin/ui/forms/switch/component.rb +4 -4
  178. data/app/components/solidus_admin/ui/icon/component.rb +4 -4
  179. data/app/components/solidus_admin/ui/icon/names.txt +973 -238
  180. data/app/components/solidus_admin/ui/modal/component.html.erb +2 -4
  181. data/app/components/solidus_admin/ui/modal/component.js +7 -1
  182. data/app/components/solidus_admin/ui/modal/component.rb +2 -2
  183. data/app/components/solidus_admin/ui/pages/index/component.rb +50 -19
  184. data/app/components/solidus_admin/ui/panel/component.rb +5 -9
  185. data/app/components/solidus_admin/ui/radio/component.rb +29 -0
  186. data/app/components/solidus_admin/ui/tab/component.rb +4 -4
  187. data/app/components/solidus_admin/ui/table/component.html.erb +11 -10
  188. data/app/components/solidus_admin/ui/table/component.js +18 -26
  189. data/app/components/solidus_admin/ui/table/component.rb +24 -18
  190. data/app/components/solidus_admin/ui/table/component.yml +1 -0
  191. data/app/components/solidus_admin/ui/table/ransack_filter/component.html.erb +1 -1
  192. data/app/components/solidus_admin/ui/table/ransack_filter/component.rb +7 -7
  193. data/app/components/solidus_admin/ui/thumbnail/component.rb +5 -5
  194. data/app/components/solidus_admin/ui/toast/component.html.erb +6 -6
  195. data/app/components/solidus_admin/ui/toast/component.rb +1 -1
  196. data/app/components/solidus_admin/ui/toggletip/component.rb +1 -1
  197. data/app/components/solidus_admin/users/addresses/component.html.erb +3 -5
  198. data/app/components/solidus_admin/users/addresses/component.rb +0 -30
  199. data/app/components/solidus_admin/users/addresses/component.yml +0 -7
  200. data/app/components/solidus_admin/users/edit/api_access/component.html.erb +6 -4
  201. data/app/components/solidus_admin/users/edit/api_access/component.yml +8 -2
  202. data/app/components/solidus_admin/users/edit/component.html.erb +15 -12
  203. data/app/components/solidus_admin/users/edit/component.rb +1 -33
  204. data/app/components/solidus_admin/users/edit/component.yml +0 -7
  205. data/app/components/solidus_admin/users/edit/tabs/component.rb +46 -0
  206. data/app/components/solidus_admin/users/edit/tabs/component.yml +6 -0
  207. data/app/components/solidus_admin/users/index/component.rb +20 -20
  208. data/app/components/solidus_admin/users/items/component.html.erb +1 -3
  209. data/app/components/solidus_admin/users/items/component.rb +18 -51
  210. data/app/components/solidus_admin/users/items/component.yml +0 -7
  211. data/app/components/solidus_admin/users/orders/component.html.erb +1 -3
  212. data/app/components/solidus_admin/users/orders/component.rb +9 -39
  213. data/app/components/solidus_admin/users/orders/component.yml +0 -6
  214. data/app/components/solidus_admin/users/store_credits/edit_amount/component.html.erb +7 -8
  215. data/app/components/solidus_admin/users/store_credits/edit_amount/component.rb +0 -5
  216. data/app/components/solidus_admin/users/store_credits/edit_amount/component.yml +0 -1
  217. data/app/components/solidus_admin/users/store_credits/edit_memo/component.html.erb +4 -4
  218. data/app/components/solidus_admin/users/store_credits/edit_memo/component.yml +0 -1
  219. data/app/components/solidus_admin/users/store_credits/edit_validity/component.html.erb +6 -7
  220. data/app/components/solidus_admin/users/store_credits/edit_validity/component.rb +0 -5
  221. data/app/components/solidus_admin/users/store_credits/index/component.html.erb +4 -6
  222. data/app/components/solidus_admin/users/store_credits/index/component.rb +10 -40
  223. data/app/components/solidus_admin/users/store_credits/index/component.yml +0 -6
  224. data/app/components/solidus_admin/users/store_credits/new/component.html.erb +12 -13
  225. data/app/components/solidus_admin/users/store_credits/new/component.rb +0 -9
  226. data/app/components/solidus_admin/users/store_credits/new/component.yml +0 -1
  227. data/app/components/solidus_admin/users/store_credits/show/component.html.erb +5 -7
  228. data/app/components/solidus_admin/users/store_credits/show/component.rb +8 -38
  229. data/app/components/solidus_admin/users/store_credits/show/component.yml +0 -6
  230. data/app/components/solidus_admin/users_and_roles/component.rb +4 -4
  231. data/app/components/solidus_admin/zones/edit/component.html.erb +1 -0
  232. data/app/components/solidus_admin/zones/edit/component.rb +4 -0
  233. data/app/components/solidus_admin/zones/form/component.html.erb +47 -0
  234. data/app/components/solidus_admin/zones/form/component.js +32 -0
  235. data/app/components/solidus_admin/zones/form/component.rb +23 -0
  236. data/app/components/solidus_admin/zones/form/component.yml +7 -0
  237. data/app/components/solidus_admin/zones/index/component.rb +57 -18
  238. data/app/components/solidus_admin/zones/new/component.html.erb +1 -0
  239. data/app/components/solidus_admin/zones/new/component.rb +4 -0
  240. data/app/controllers/concerns/solidus_admin/moveable.rb +31 -0
  241. data/app/controllers/solidus_admin/addresses_controller.rb +9 -11
  242. data/app/controllers/solidus_admin/adjustments_controller.rb +5 -6
  243. data/app/controllers/solidus_admin/base_controller.rb +8 -7
  244. data/app/controllers/solidus_admin/controller_helpers/authorization.rb +1 -1
  245. data/app/controllers/solidus_admin/controller_helpers/locale.rb +1 -1
  246. data/app/controllers/solidus_admin/controller_helpers/pagination.rb +37 -0
  247. data/app/controllers/solidus_admin/controller_helpers/search.rb +5 -5
  248. data/app/controllers/solidus_admin/controller_helpers/theme.rb +2 -2
  249. data/app/controllers/solidus_admin/customers_controller.rb +3 -3
  250. data/app/controllers/solidus_admin/line_items_controller.rb +3 -3
  251. data/app/controllers/solidus_admin/option_types_controller.rb +11 -32
  252. data/app/controllers/solidus_admin/option_values_controller.rb +54 -0
  253. data/app/controllers/solidus_admin/orders_controller.rb +25 -19
  254. data/app/controllers/solidus_admin/payment_methods_controller.rb +23 -28
  255. data/app/controllers/solidus_admin/product_option_types_controller.rb +5 -0
  256. data/app/controllers/solidus_admin/product_taxons_controller.rb +58 -0
  257. data/app/controllers/solidus_admin/products_controller.rb +24 -28
  258. data/app/controllers/solidus_admin/reimbursement_types_controller.rb +3 -3
  259. data/app/controllers/solidus_admin/resources_controller.rb +59 -20
  260. data/app/controllers/solidus_admin/shipping_methods_controller.rb +4 -4
  261. data/app/controllers/solidus_admin/states_controller.rb +30 -0
  262. data/app/controllers/solidus_admin/stock_items_controller.rb +11 -6
  263. data/app/controllers/solidus_admin/stock_locations_controller.rb +25 -26
  264. data/app/controllers/solidus_admin/store_credits_controller.rb +9 -9
  265. data/app/controllers/solidus_admin/stores_controller.rb +43 -9
  266. data/app/controllers/solidus_admin/tax_rates_controller.rb +9 -22
  267. data/app/controllers/solidus_admin/taxonomies_controller.rb +5 -21
  268. data/app/controllers/solidus_admin/users_controller.rb +16 -16
  269. data/app/controllers/solidus_admin/zones_controller.rb +6 -26
  270. data/app/helpers/solidus_admin/flash_helper.rb +14 -0
  271. data/app/helpers/solidus_admin/last_login_helper.rb +2 -2
  272. data/app/helpers/solidus_admin/permission_sets_helper.rb +3 -3
  273. data/app/helpers/solidus_admin/solidus_form_helper.rb +9 -0
  274. data/app/helpers/solidus_admin/stimulus_helper.rb +29 -0
  275. data/app/helpers/solidus_admin/void_elements_helper.rb +1 -1
  276. data/app/javascript/solidus_admin/application.js +10 -1
  277. data/app/javascript/solidus_admin/confirm_modal.js +24 -0
  278. data/app/javascript/solidus_admin/controllers/custom_validity_controller.js +12 -0
  279. data/app/javascript/solidus_admin/controllers/sortable_controller.js +9 -2
  280. data/app/javascript/solidus_admin/tom-select/plugins/patch_scroll.js +19 -0
  281. data/app/javascript/solidus_admin/tom-select/plugins/remote_with_pagination.js +67 -0
  282. data/app/javascript/solidus_admin/tom-select/plugins/stash_on_search.js +68 -0
  283. data/app/javascript/solidus_admin/tom-select/tom-select.js +11 -0
  284. data/app/javascript/solidus_admin/utils.js +40 -0
  285. data/app/javascript/solidus_admin/web_components/solidus_select.js +90 -0
  286. data/app/javascript/vendor/custom_elements.js +3 -0
  287. data/app/lib/solidus_admin/form_builder.rb +58 -0
  288. data/app/views/layouts/solidus_admin/application.html.erb +6 -8
  289. data/app/views/layouts/solidus_admin/preview.html.erb +1 -1
  290. data/app/views/solidus_admin/option_values/create.turbo_stream.erb +3 -0
  291. data/app/views/solidus_admin/option_values/destroy.turbo_stream.erb +3 -0
  292. data/app/views/solidus_admin/option_values/update.turbo_stream.erb +3 -0
  293. data/config/importmap.rb +9 -0
  294. data/config/initializers/view_component.rb +1 -1
  295. data/config/locales/option_types.en.yml +5 -1
  296. data/config/locales/option_values.en.yml +9 -0
  297. data/config/locales/payment_methods.en.yml +5 -1
  298. data/config/locales/product_taxons.en.yml +6 -0
  299. data/config/locales/products.en.yml +2 -0
  300. data/config/locales/solidus_select.yml +6 -0
  301. data/config/locales/stock_locations.en.yml +4 -0
  302. data/config/locales/stores.en.yml +22 -0
  303. data/config/locales/tax_rates.en.yml +4 -0
  304. data/config/locales/zones.en.yml +4 -0
  305. data/config/routes.rb +21 -9
  306. data/config/tailwind.config.js +6 -2
  307. data/docs/components.md +2 -2
  308. data/docs/index_pages.md +11 -5
  309. data/docs/stimulusjs.md +1 -1
  310. data/eslint.config.mjs +25 -0
  311. data/lib/generators/solidus_admin/component/component_generator.rb +10 -6
  312. data/lib/generators/solidus_admin/install/install_generator.rb +24 -5
  313. data/lib/generators/solidus_admin/install/templates/config/initializers/solidus_admin.rb.tt +6 -0
  314. data/lib/solidus_admin/admin_resources.rb +1 -1
  315. data/lib/solidus_admin/configuration.rb +14 -14
  316. data/lib/solidus_admin/engine.rb +3 -2
  317. data/lib/solidus_admin/importmap.rb +1 -1
  318. data/lib/solidus_admin/menu_item.rb +1 -1
  319. data/lib/solidus_admin/preview.rb +1 -0
  320. data/lib/solidus_admin/testing_support/admin_assets.rb +1 -1
  321. data/lib/solidus_admin/testing_support/feature_helpers.rb +77 -3
  322. data/lib/solidus_admin/testing_support/shared_examples/crud_resource_requests.rb +43 -36
  323. data/lib/solidus_admin/testing_support/shared_examples/moveable.rb +48 -0
  324. data/lib/solidus_admin/testing_support/shared_examples/promotion_categories_features.rb +5 -11
  325. data/lib/solidus_admin/version.rb +1 -1
  326. data/lib/tasks/tailwind.rake +1 -1
  327. data/solidus_admin.gemspec +24 -21
  328. metadata +173 -29
  329. data/.eslintrc.json +0 -7
  330. data/app/components/solidus_admin/products/show/component.js +0 -9
  331. data/app/components/solidus_admin/ui/forms/input/component.js +0 -15
  332. data/app/components/solidus_admin/users/edit/api_access/component.js +0 -9
  333. data/app/javascript/solidus_admin/controllers/confirm_controller.js +0 -21
  334. data/lib/solidus_admin/testing_support/shared_examples/bulk_delete_resources.rb +0 -20
  335. /data/app/{components/solidus_admin/ui/toast/component.js → javascript/solidus_admin/controllers/alert_animation_controller.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusAdmin
4
- class StoresController < SolidusAdmin::BaseController
4
+ class StoresController < SolidusAdmin::ResourcesController
5
5
  include SolidusAdmin::ControllerHelpers::Search
6
6
 
7
7
  def index
@@ -10,26 +10,60 @@ module SolidusAdmin
10
10
  param: :q
11
11
  )
12
12
 
13
- set_page_and_extract_portion_from(stores)
13
+ @page = paginate(stores)
14
14
 
15
15
  respond_to do |format|
16
- format.html { render component('stores/index').new(page: @page) }
16
+ format.html { render component("stores/index").new(page: @page) }
17
17
  end
18
18
  end
19
19
 
20
20
  def destroy
21
- @stores = Spree::Store.where(id: params[:id])
21
+ @resource = resource_class.where(id: params[:id])
22
22
 
23
- Spree::Store.transaction { @stores.destroy_all }
23
+ failed = @resource.destroy_all.reject(&:destroyed?)
24
+ if failed.none?
25
+ flash[:notice] = t(".success")
26
+ else
27
+ failure_summary = failed.map { |record|
28
+ t ".error.description",
29
+ name: record.name,
30
+ reason: record.errors.full_messages.join(", ")
31
+ }.join("<br/>")
24
32
 
25
- flash[:notice] = t('.success')
26
- redirect_back_or_to stores_path, status: :see_other
33
+ flash[:alert] = {
34
+ danger: {title: t(".error.title"), message: failure_summary}
35
+ }
36
+ end
37
+
38
+ redirect_to after_destroy_path, status: :see_other
27
39
  end
28
40
 
29
41
  private
30
42
 
31
- def store_params
32
- params.require(:store).permit(:store_id, permitted_store_attributes)
43
+ def resource_class = Spree::Store
44
+
45
+ def resources_collection = Spree::Store
46
+
47
+ def permitted_resource_params
48
+ permitted = [
49
+ :name,
50
+ :url,
51
+ :code,
52
+ :meta_description,
53
+ :meta_keywords,
54
+ :seo_title,
55
+ :mail_from_address,
56
+ :default_currency,
57
+ :cart_tax_country_iso,
58
+ {available_locales: []}
59
+ ]
60
+ # This check can be removed once we drop support for Solidus 4.7 and earlier.
61
+ permitted << {address_attributes: Spree::PermittedAttributes.address_attributes} if Spree::Store.reflect_on_association(:address)
62
+
63
+ params.require(:store).permit(*permitted).tap do |store_params|
64
+ without_address_parameter = store_params[:address_attributes]&.except(:country_id, :state_id, :reverse_charge_status)&.compact_blank&.empty?
65
+ store_params.delete(:address_attributes) if without_address_parameter
66
+ end
33
67
  end
34
68
  end
35
69
  end
@@ -1,35 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusAdmin
4
- class TaxRatesController < SolidusAdmin::BaseController
4
+ class TaxRatesController < SolidusAdmin::ResourcesController
5
5
  include SolidusAdmin::ControllerHelpers::Search
6
6
 
7
- def index
8
- tax_rates = apply_search_to(
9
- Spree::TaxRate.order(created_at: :desc, id: :desc),
10
- param: :q,
11
- )
12
-
13
- set_page_and_extract_portion_from(tax_rates)
14
-
15
- respond_to do |format|
16
- format.html { render component('tax_rates/index').new(page: @page) }
17
- end
18
- end
19
-
20
- def destroy
21
- @tax_rates = Spree::TaxRate.where(id: params[:id])
7
+ private
22
8
 
23
- Spree::TaxRate.transaction { @tax_rates.destroy_all }
9
+ def resource_class = Spree::TaxRate
24
10
 
25
- flash[:notice] = t('.success')
26
- redirect_back_or_to tax_rates_path, status: :see_other
11
+ def resources_collection
12
+ resource_class.includes(:zone, :tax_categories, :calculator)
27
13
  end
28
14
 
29
- private
15
+ def resources_sorting_options = {created_at: :desc, id: :desc}
30
16
 
31
- def tax_rate_params
32
- params.require(:tax_rate).permit(:tax_rate_id, permitted_tax_rate_attributes)
17
+ def permitted_resource_params
18
+ params.require(:tax_rate).permit(:name, :zone_id, :show_rate_in_label, :calculator_type, :amount, :level,
19
+ :included_in_price, :starts_at, :expires_at, tax_category_ids: [])
33
20
  end
34
21
  end
35
22
  end
@@ -3,27 +3,18 @@
3
3
  module SolidusAdmin
4
4
  class TaxonomiesController < SolidusAdmin::BaseController
5
5
  include SolidusAdmin::ControllerHelpers::Search
6
-
7
- before_action :load_taxonomy, only: [:move]
6
+ include SolidusAdmin::Moveable
8
7
 
9
8
  def index
10
9
  taxonomies = apply_search_to(
11
10
  Spree::Taxonomy.all,
12
- param: :q,
11
+ param: :q
13
12
  )
14
13
 
15
- set_page_and_extract_portion_from(taxonomies)
14
+ @page = paginate(taxonomies)
16
15
 
17
16
  respond_to do |format|
18
- format.html { render component('taxonomies/index').new(page: @page) }
19
- end
20
- end
21
-
22
- def move
23
- @taxonomy.insert_at(params[:position].to_i)
24
-
25
- respond_to do |format|
26
- format.js { head :no_content }
17
+ format.html { render component("taxonomies/index").new(page: @page) }
27
18
  end
28
19
  end
29
20
 
@@ -32,15 +23,8 @@ module SolidusAdmin
32
23
 
33
24
  Spree::Taxonomy.transaction { @taxonomies.destroy_all }
34
25
 
35
- flash[:notice] = t('.success')
26
+ flash[:notice] = t(".success")
36
27
  redirect_back_or_to taxonomies_path, status: :see_other
37
28
  end
38
-
39
- private
40
-
41
- def load_taxonomy
42
- @taxonomy = Spree::Taxonomy.find(params[:id])
43
- authorize! action_name, @taxonomy
44
- end
45
29
  end
46
30
  end
@@ -8,28 +8,28 @@ module SolidusAdmin
8
8
  before_action :set_user, only: [:edit, :addresses, :update_addresses, :orders, :items]
9
9
 
10
10
  search_scope(:all, default: true)
11
- search_scope(:customers) { _1.left_outer_joins(:role_users).where(role_users: { id: nil }) }
11
+ search_scope(:customers) { _1.left_outer_joins(:role_users).where(role_users: {id: nil}) }
12
12
  search_scope(:admin) { _1.joins(:role_users).distinct }
13
13
  search_scope(:with_orders) { _1.joins(:orders).distinct }
14
- search_scope(:without_orders) { _1.left_outer_joins(:orders).where(orders: { id: nil }) }
14
+ search_scope(:without_orders) { _1.left_outer_joins(:orders).where(orders: {id: nil}) }
15
15
 
16
16
  def index
17
17
  users = apply_search_to(
18
18
  Spree.user_class.order(created_at: :desc, id: :desc),
19
- param: :q,
19
+ param: :q
20
20
  )
21
21
 
22
- set_page_and_extract_portion_from(users)
22
+ @page = paginate(users)
23
23
 
24
24
  respond_to do |format|
25
- format.html { render component('users/index').new(page: @page) }
25
+ format.html { render component("users/index").new(page: @page) }
26
26
  end
27
27
  end
28
28
 
29
29
  def addresses
30
30
  respond_to do |format|
31
31
  format.turbo_stream { render turbo_stream: '<turbo-stream action="refresh" />' }
32
- format.html { render component('users/addresses').new(user: @user) }
32
+ format.html { render component("users/addresses").new(user: @user) }
33
33
  end
34
34
  end
35
35
 
@@ -37,15 +37,15 @@ module SolidusAdmin
37
37
  set_address_from_params
38
38
 
39
39
  if @address.valid? && @user.update(user_params)
40
- flash[:success] = t(".#{@type}.success")
40
+ flash[:notice] = t(".#{@type}.success")
41
41
 
42
42
  respond_to do |format|
43
43
  format.turbo_stream { render turbo_stream: '<turbo-stream action="refresh" />' }
44
- format.html { render component('users/addresses').new(user: @user) }
44
+ format.html { render component("users/addresses").new(user: @user) }
45
45
  end
46
46
  else
47
47
  respond_to do |format|
48
- format.html { render component('users/addresses').new(user: @user, address: @address, type: @type), status: :unprocessable_entity }
48
+ format.html { render component("users/addresses").new(user: @user, address: @address, type: @type), status: :unprocessable_entity }
49
49
  end
50
50
  end
51
51
  end
@@ -54,7 +54,7 @@ module SolidusAdmin
54
54
  set_orders
55
55
 
56
56
  respond_to do |format|
57
- format.html { render component('users/orders').new(user: @user, orders: @orders) }
57
+ format.html { render component("users/orders").new(user: @user, orders: @orders) }
58
58
  end
59
59
  end
60
60
 
@@ -62,13 +62,13 @@ module SolidusAdmin
62
62
  set_items
63
63
 
64
64
  respond_to do |format|
65
- format.html { render component('users/items').new(user: @user, items: @items) }
65
+ format.html { render component("users/items").new(user: @user, items: @items) }
66
66
  end
67
67
  end
68
68
 
69
69
  def edit
70
70
  respond_to do |format|
71
- format.html { render component('users/edit').new(user: @user) }
71
+ format.html { render component("users/edit").new(user: @user) }
72
72
  end
73
73
  end
74
74
 
@@ -77,7 +77,7 @@ module SolidusAdmin
77
77
 
78
78
  Spree.user_class.transaction { @users.destroy_all }
79
79
 
80
- flash[:notice] = t('.success')
80
+ flash[:notice] = t(".success")
81
81
  redirect_back_or_to users_path, status: :see_other
82
82
  end
83
83
 
@@ -112,13 +112,13 @@ module SolidusAdmin
112
112
  def set_orders
113
113
  params[:q] ||= {}
114
114
  @search = Spree::Order.reverse_chronological.ransack(params[:q].merge(user_id_eq: @user.id))
115
- @orders = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page])
115
+ @orders = @search.result.page(params[:page]).per(Spree::Config.admin_products_per_page)
116
116
  end
117
117
 
118
118
  def set_items
119
119
  params[:q] ||= {}
120
- @search = Spree::Order.reverse_chronological.includes(line_items: { variant: [:product, { option_values: :option_type }] }).ransack(params[:q].merge(user_id_eq: @user.id))
121
- @orders = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page])
120
+ @search = Spree::Order.reverse_chronological.includes(line_items: {variant: [:product, {option_values: :option_type}]}).ransack(params[:q].merge(user_id_eq: @user.id))
121
+ @orders = @search.result.page(params[:page]).per(Spree::Config.admin_products_per_page)
122
122
  @items = @orders&.map(&:line_items)&.flatten
123
123
  end
124
124
 
@@ -1,35 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidusAdmin
4
- class ZonesController < SolidusAdmin::BaseController
5
- include SolidusAdmin::ControllerHelpers::Search
6
-
7
- def index
8
- zones = apply_search_to(
9
- Spree::Zone.order(id: :desc),
10
- param: :q
11
- )
12
-
13
- set_page_and_extract_portion_from(zones)
14
-
15
- respond_to do |format|
16
- format.html { render component('zones/index').new(page: @page) }
17
- end
18
- end
19
-
20
- def destroy
21
- @zones = Spree::Zone.where(id: params[:id])
22
-
23
- Spree::Zone.transaction { @zones.destroy_all }
4
+ class ZonesController < SolidusAdmin::ResourcesController
5
+ private
24
6
 
25
- flash[:notice] = t('.success')
26
- redirect_back_or_to zones_path, status: :see_other
27
- end
7
+ def resource_class = Spree::Zone
28
8
 
29
- private
9
+ def resources_collection = Spree::Zone.includes(zone_members: :zoneable)
30
10
 
31
- def zone_params
32
- params.require(:zone).permit(:zone_id, permitted_zone_attributes)
11
+ def permitted_resource_params
12
+ params.require(:zone).permit(:name, :description, state_ids: [], country_ids: [])
33
13
  end
34
14
  end
35
15
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Reserve :alert for messages that should go in UI alert component. Everything else will be shown in UI toast.
4
+ module SolidusAdmin
5
+ module FlashHelper
6
+ def toasts
7
+ flash.to_hash.with_indifferent_access.except(:alert)
8
+ end
9
+
10
+ def alerts
11
+ flash.to_hash.with_indifferent_access.fetch(:alert, {})
12
+ end
13
+ end
14
+ end
@@ -3,10 +3,10 @@
3
3
  module SolidusAdmin
4
4
  module LastLoginHelper
5
5
  def last_login(user)
6
- return t('solidus_admin.users.last_login.never') if user.try(:last_sign_in_at).blank?
6
+ return t("solidus_admin.users.last_login.never") if user.try(:last_sign_in_at).blank?
7
7
 
8
8
  t(
9
- 'solidus_admin.users.last_login.login_time_ago',
9
+ "solidus_admin.users.last_login.login_time_ago",
10
10
  # @note The second `.try` is here for the specs and for setups that use a
11
11
  # custom User class which may not have this attribute.
12
12
  last_login_time: time_ago_in_words(user.try(:last_sign_in_at))
@@ -18,13 +18,13 @@ module SolidusAdmin
18
18
  case permission.privilege
19
19
  when "display"
20
20
  grouped_permissions[group_key] ||= []
21
- grouped_permissions[group_key] << { label: view_label, id: permission.id }
21
+ grouped_permissions[group_key] << {label: view_label, id: permission.id}
22
22
  when "management"
23
23
  grouped_permissions[group_key] ||= []
24
- grouped_permissions[group_key] << { label: edit_label, id: permission.id }
24
+ grouped_permissions[group_key] << {label: edit_label, id: permission.id}
25
25
  else
26
26
  grouped_permissions[:other] ||= []
27
- grouped_permissions[:other] << { label: permission.name, id: permission.id }
27
+ grouped_permissions[:other] << {label: permission.name, id: permission.id}
28
28
  end
29
29
  end
30
30
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusAdmin
4
+ module SolidusFormHelper
5
+ def solidus_form_for(*args, **kwargs, &block)
6
+ form_for(*args, **kwargs, builder: SolidusAdmin::FormBuilder, &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Simple shorthands and helpers for stimulus data attributes to avoid writing clumsy interpolations with `stimulus_id`
4
+ # Before: "data-#{stimulus_id}-target": "wrapper"
5
+ # After: stimulus_target("wrapper")
6
+
7
+ module SolidusAdmin
8
+ module StimulusHelper
9
+ def stimulus_controller
10
+ {"data-controller": stimulus_id}
11
+ end
12
+
13
+ def stimulus_action(action, on: nil)
14
+ action_construct = []
15
+ action_construct << "#{on}->" if on.present?
16
+ action_construct << "#{stimulus_id}##{action}"
17
+
18
+ {"data-action": action_construct.join}
19
+ end
20
+
21
+ def stimulus_target(target)
22
+ {"data-#{stimulus_id}-target": target}
23
+ end
24
+
25
+ def stimulus_value(name:, value:)
26
+ {"data-#{stimulus_id}-#{name}-value": value}
27
+ end
28
+ end
29
+ end
@@ -3,7 +3,7 @@
3
3
  module SolidusAdmin
4
4
  module VoidElementsHelper
5
5
  # https://github.com/rails/rails/blob/194d697036c61af0caa66de5659721ded2478ce9/actionview/lib/action_view/helpers/tag_helper.rb#L84
6
- HTML_VOID_ELEMENTS = %i(area base br col embed hr img input keygen link meta source track wbr)
6
+ HTML_VOID_ELEMENTS = %i[area base br col embed hr img input keygen link meta source track wbr]
7
7
 
8
8
  # @param element [Symbol]
9
9
  def void_element?(element)
@@ -1,2 +1,11 @@
1
- import "@hotwired/turbo-rails"
1
+ import { Turbo } from "@hotwired/turbo-rails"
2
+ import "vendor/custom_elements"
2
3
  import "solidus_admin/controllers"
4
+ import { openConfirmModal } from "solidus_admin/confirm_modal"
5
+ import "solidus_admin/web_components/solidus_select"
6
+
7
+ if (Turbo.config) {
8
+ Turbo.config.forms.confirm = openConfirmModal
9
+ } else {
10
+ window.Turbo.setConfirmMethod(openConfirmModal)
11
+ }
@@ -0,0 +1,24 @@
1
+ import { application } from "solidus_admin/controllers/application"
2
+
3
+ /*
4
+ * Opens a confirmation modal with the given message and options.
5
+ * This is used as the Turbo confirm modal replacement. It returns a
6
+ * Promise that resolves to true if the user confirms, or false if
7
+ * the user cancels.
8
+ *
9
+ * @param {string} message - The message to display in the confirmation modal.
10
+ * @param {HTMLFormElement} formElement - Form element that triggered the
11
+ * confirmation.
12
+ * @param {HTMLElement} submitter - The element that triggered the form
13
+ * submission.
14
+ * @returns {Promise<boolean>} - A promise that resolves to true if the user
15
+ * confirms, or false if the user cancels.
16
+ */
17
+ export function openConfirmModal(message, formElement, submitter) {
18
+ const element = document.getElementById("confirm")
19
+ const controller = application.getControllerForElementAndIdentifier(element, "layout--confirm")
20
+ const details = submitter?.dataset.confirmDetails ?? formElement?.dataset.confirmDetails ?? ""
21
+ const buttonText = submitter?.dataset.confirmButton ?? formElement?.dataset.confirmButton
22
+
23
+ return controller.open(message, { details, buttonText })
24
+ }
@@ -0,0 +1,12 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+ import { setValidity } from "solidus_admin/utils";
3
+
4
+ export default class extends Controller {
5
+ static values = {
6
+ errorMessage: String,
7
+ }
8
+
9
+ connect() {
10
+ setValidity(this.element, this.errorMessageValue);
11
+ }
12
+ }
@@ -4,9 +4,11 @@ import { patch } from '@rails/request.js'
4
4
 
5
5
  export default class extends Controller {
6
6
  static values = {
7
- param: { type: String, default: 'postion' },
7
+ param: { type: String, default: 'position' },
8
8
  handle: { type: String, default: null },
9
9
  animation: { type: Number, default: 150 },
10
+ page: { type: Number },
11
+ perPage: { type: Number },
10
12
  }
11
13
 
12
14
  connect() {
@@ -21,7 +23,12 @@ export default class extends Controller {
21
23
  if (!item.dataset.sortableUrl) return
22
24
 
23
25
  const data = new FormData()
24
- data.append(this.paramValue, newIndex + 1)
26
+ let newPosition = newIndex + 1;
27
+ if (this.pageValue && this.perPageValue) {
28
+ const offset = (this.pageValue - 1) * this.perPageValue;
29
+ newPosition += offset;
30
+ }
31
+ data.append(this.paramValue, newPosition)
25
32
 
26
33
  return await patch(item.dataset.sortableUrl, { body: data, responseKind: "js" })
27
34
  }
@@ -0,0 +1,19 @@
1
+ const patch = function(fnName) {
2
+ const originalFn = this[fnName];
3
+ this.hook("instead", fnName, function() {
4
+ const originalScrollToOption = this.scrollToOption;
5
+
6
+ this.scrollToOption = () => {};
7
+ originalFn.apply(this, arguments);
8
+ this.scrollToOption = originalScrollToOption;
9
+ });
10
+ }
11
+
12
+ // https://github.com/orchidjs/tom-select/issues/556
13
+ // https://github.com/orchidjs/tom-select/issues/867
14
+ export default function() {
15
+ this.on("initialize", function() {
16
+ patch.call(this, "onOptionSelect");
17
+ patch.call(this, "loadCallback");
18
+ })
19
+ }
@@ -0,0 +1,67 @@
1
+ import { parseLinkHeader } from "solidus_admin/utils";
2
+
3
+ // Fetch all options from remote source and setup pagination if needed
4
+ const loadOptions = async function(query, callback) {
5
+ const { options, next } = await fetchOptions.call(this, query);
6
+ if (next) {
7
+ this.setNextUrl(query, next);
8
+ }
9
+
10
+ callback(options);
11
+ }
12
+
13
+ // Fetch options from remote source. If options data is nested in json response, specify path to it with "jsonPath"
14
+ // E.g. https://whatcms.org/API/List data is deep nested in json response: `{ result: { list: [...] } }`, so
15
+ // in order to access it, pass config options to this plugin as follows:
16
+ // {
17
+ // src: "https://whatcms.org/API/List",
18
+ // jsonPath: "result.list"
19
+ // }
20
+ const fetchOptions = async function(query) {
21
+ const dataPath = this.settings.jsonPath;
22
+ const response = await fetch(buildUrl.call(this, query), { headers: { "Accept": "application/json" } });
23
+ if (!response.ok) {
24
+ return { options: [] };
25
+ }
26
+
27
+ const next = parseLinkHeader(response.headers.get("Link")).next;
28
+ const json = await response.json();
29
+
30
+ let options;
31
+ if (!dataPath) {
32
+ options = json;
33
+ } else {
34
+ options = dataPath.split('.').reduce((acc, key) => acc && acc[key], json);
35
+ }
36
+
37
+ return { options, next };
38
+ }
39
+
40
+ const buildUrl = function(query) {
41
+ const url = new URL(this.getUrl(query));
42
+ const queryParam = this.settings.queryParam;
43
+ if (!query || !queryParam) return url.toString();
44
+
45
+ url.searchParams.set(queryParam, query);
46
+ return url.toString();
47
+ }
48
+
49
+ export default function(config) {
50
+ this.settings.firstUrl = () => config.src;
51
+ this.settings.load = loadOptions.bind(this);
52
+ this.settings.preload = config.preload;
53
+ this.settings.searchField = [this.settings.labelField];
54
+ this.settings.jsonPath = config.jsonPath;
55
+ this.settings.queryParam = config.queryParam;
56
+ this.settings.render = Object.assign(this.settings.render, {
57
+ loading: function() {
58
+ return `<div class='loading'>${config.loadingMessage}</div>`;
59
+ },
60
+ loading_more: function() {
61
+ return `<div class='loading-more'>${config.loadingMoreMessage}</div>`;
62
+ },
63
+ no_more_results: function() {},
64
+ });
65
+
66
+ this.require("virtual_scroll");
67
+ }
@@ -0,0 +1,68 @@
1
+ // Substitute default TomSelect functionality for single selects, where typing in the select field while there is
2
+ // an option selected shows both selected option and the search term.
3
+ // Instead, hide the selected option when typing and bring it back when leaving the field.
4
+ class Stash {
5
+ #content = {};
6
+
7
+ put(value, data) {
8
+ this.#content["value"] = value;
9
+ this.#content["data"] = data;
10
+ }
11
+
12
+ pop() {
13
+ const { value, data } = this.#content;
14
+ this.clear();
15
+ return { value, data };
16
+ }
17
+
18
+ clear() {
19
+ this.#content = {};
20
+ }
21
+
22
+ get isEmpty() {
23
+ return Object.keys(this.#content).length === 0;
24
+ }
25
+ }
26
+
27
+ export default function() {
28
+ if (this.settings.mode === 'multi') return;
29
+
30
+ this.stash = new Stash();
31
+
32
+ this.stashSelected = function() {
33
+ if (!this.stash.isEmpty) return;
34
+ if (!this.items.length) return;
35
+
36
+ const currentValue = this.items[0];
37
+ this.stash.put(currentValue, this.options[currentValue]);
38
+ this.clear(true);
39
+ };
40
+
41
+ this.unstashSelected = function() {
42
+ if (this.stash.isEmpty) return;
43
+
44
+ const { value, data } = this.stash.pop();
45
+ // In case this is a select with remote source, options are refreshed on each search, so we need to put the option
46
+ // back in the list for TomSelect to pick it as a selected item.
47
+ // If the option is already in the list, it will be ignored.
48
+ this.addOption(data);
49
+ this.setValue(value, true);
50
+ };
51
+
52
+ // save current selected option in case user won't select anything
53
+ this.on("type", function() {
54
+ this.stashSelected();
55
+ });
56
+
57
+ // new option has been selected, no need to hold on to previous option
58
+ this.on("item_add", function() {
59
+ this.stash.clear();
60
+ });
61
+
62
+ // if nothing has been selected restore previous option
63
+ this.on("blur", function() {
64
+ if (this.items.length) return;
65
+
66
+ this.unstashSelected();
67
+ });
68
+ }
@@ -0,0 +1,11 @@
1
+ import TomSelect from "tom-select";
2
+
3
+ import patchScroll from "./plugins/patch_scroll.js";
4
+ import stashOnSearch from "./plugins/stash_on_search.js";
5
+ import remoteWithPagination from "./plugins/remote_with_pagination.js";
6
+
7
+ TomSelect.define("patch_scroll", patchScroll);
8
+ TomSelect.define("stash_on_search", stashOnSearch);
9
+ TomSelect.define("remote_with_pagination", remoteWithPagination);
10
+
11
+ export default TomSelect;