avo 3.30.4 → 4.0.0.beta.1

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 (466) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +18 -1
  3. data/Gemfile.lock +257 -174
  4. data/README.md +1 -1
  5. data/app/assets/builds/avo/application.css +13942 -0
  6. data/app/assets/builds/avo/application.js +1160 -0
  7. data/app/assets/builds/avo/application.js.map +7 -0
  8. data/app/assets/builds/avo/late-registration.js +2 -0
  9. data/app/assets/builds/avo/late-registration.js.map +7 -0
  10. data/app/assets/config/avo_manifest.js +2 -1
  11. data/app/assets/stylesheets/application.css +241 -0
  12. data/app/assets/stylesheets/css/button-group.css +23 -0
  13. data/app/assets/stylesheets/css/components/avatar.css +128 -0
  14. data/app/assets/stylesheets/css/components/breadcrumbs.css +43 -0
  15. data/app/assets/stylesheets/css/components/button.css +343 -0
  16. data/app/assets/stylesheets/css/components/color_scheme_switcher.css +226 -0
  17. data/app/assets/stylesheets/css/components/discreet_information.css +49 -0
  18. data/app/assets/stylesheets/css/components/field-wrapper.css +107 -0
  19. data/app/assets/stylesheets/css/components/grid.css +61 -0
  20. data/app/assets/stylesheets/css/components/input.css +312 -0
  21. data/app/assets/stylesheets/css/components/modal.css +228 -0
  22. data/app/assets/stylesheets/css/components/tooltip.css +25 -0
  23. data/app/assets/stylesheets/css/components/ui/badge.css +143 -0
  24. data/app/assets/stylesheets/css/components/ui/card.css +95 -0
  25. data/app/assets/stylesheets/css/components/ui/checkbox.css +50 -0
  26. data/app/assets/stylesheets/css/components/ui/description_list.css +3 -0
  27. data/app/assets/stylesheets/css/components/ui/dropdown.css +68 -0
  28. data/app/assets/stylesheets/css/components/ui/file_upload_input.css +94 -0
  29. data/app/assets/stylesheets/css/components/ui/file_upload_item.css +78 -0
  30. data/app/assets/stylesheets/css/components/ui/panel.css +59 -0
  31. data/app/assets/stylesheets/css/components/ui/panel_header.css +48 -0
  32. data/app/assets/stylesheets/css/components/ui/radio.css +22 -0
  33. data/app/assets/stylesheets/css/components/ui/tabs.css +74 -0
  34. data/app/assets/stylesheets/css/css-animations.css +54 -0
  35. data/app/assets/stylesheets/css/fields/code.css +75 -9
  36. data/app/assets/stylesheets/css/fields/easy-mde.css +7 -0
  37. data/app/assets/stylesheets/css/fields/key_value.css +97 -0
  38. data/app/assets/stylesheets/css/fields/progress.css +4 -4
  39. data/app/assets/stylesheets/css/fields/status.css +7 -1
  40. data/app/assets/stylesheets/css/fields/tags.css +33 -16
  41. data/app/assets/stylesheets/css/fields/tiptap.css +17 -15
  42. data/app/assets/stylesheets/css/fields/trix.css +62 -2
  43. data/app/assets/stylesheets/css/fonts.css +24 -24
  44. data/app/assets/stylesheets/css/layout.css +135 -0
  45. data/app/assets/stylesheets/css/pagination.css +114 -78
  46. data/app/assets/stylesheets/css/resource-controls.css +13 -0
  47. data/app/assets/stylesheets/css/search.css +22 -12
  48. data/app/assets/stylesheets/css/sidebar.css +310 -24
  49. data/app/assets/stylesheets/css/table.css +60 -0
  50. data/app/assets/stylesheets/css/tooltips.css +1 -1
  51. data/app/assets/stylesheets/css/typography.css +10 -1
  52. data/app/assets/stylesheets/css/variables.css +318 -0
  53. data/app/assets/svgs/avo/moon-plus-plus.svg +1 -0
  54. data/app/components/avo/actions_component.html.erb +30 -36
  55. data/app/components/avo/actions_component.rb +8 -11
  56. data/app/components/avo/alert_component.html.erb +3 -3
  57. data/app/components/avo/alert_component.rb +1 -1
  58. data/app/components/avo/asset_manager/javascript_component.html.erb +1 -2
  59. data/app/components/avo/backtrace_alert_component.html.erb +4 -4
  60. data/app/components/avo/base_component.rb +3 -4
  61. data/app/components/avo/breadcrumb_element_component.html.erb +17 -0
  62. data/app/components/avo/breadcrumb_element_component.rb +21 -0
  63. data/app/components/avo/breadcrumbs_component.html.erb +19 -0
  64. data/app/components/avo/breadcrumbs_component.rb +5 -0
  65. data/app/components/avo/button_component.rb +20 -126
  66. data/app/components/avo/clipboard_component.html.erb +3 -2
  67. data/app/components/avo/clipboard_component.rb +1 -1
  68. data/app/components/avo/component_missing_component.rb +11 -0
  69. data/app/components/avo/cover_component.html.erb +3 -0
  70. data/app/components/avo/cover_component.rb +25 -0
  71. data/app/components/avo/debug/status_component.html.erb +59 -0
  72. data/app/components/avo/debug/status_component.rb +30 -0
  73. data/app/components/avo/description_list_component.rb +11 -0
  74. data/app/components/avo/discreet_information_component.html.erb +31 -6
  75. data/app/components/avo/discreet_information_component.rb +23 -32
  76. data/app/components/avo/divider_component.html.erb +2 -2
  77. data/app/components/avo/empty_state_component.html.erb +2 -9
  78. data/app/components/avo/empty_state_component.rb +0 -8
  79. data/app/components/avo/field_wrapper_component.html.erb +21 -22
  80. data/app/components/avo/field_wrapper_component.rb +9 -18
  81. data/app/components/avo/fields/avatar_field/index_component.html.erb +9 -0
  82. data/app/components/avo/fields/avatar_field/index_component.rb +4 -0
  83. data/app/components/avo/fields/badge_field/index_component.html.erb +7 -1
  84. data/app/components/avo/fields/badge_field/show_component.html.erb +6 -1
  85. data/app/components/avo/fields/belongs_to_field/edit_component.html.erb +16 -14
  86. data/app/components/avo/fields/belongs_to_field/edit_component.rb +13 -3
  87. data/app/components/avo/fields/boolean_field/edit_component.html.erb +2 -2
  88. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  89. data/app/components/avo/fields/boolean_group_field/edit_component.rb +2 -3
  90. data/app/components/avo/fields/code_field/show_component.html.erb +1 -1
  91. data/app/components/avo/fields/common/boolean_check_component.rb +3 -3
  92. data/app/components/avo/fields/common/boolean_group_component.html.erb +2 -2
  93. data/app/components/avo/fields/common/files/controls_component.html.erb +30 -27
  94. data/app/components/avo/fields/common/files/controls_component.rb +0 -1
  95. data/app/components/avo/fields/common/files/list_viewer_component.html.erb +4 -5
  96. data/app/components/avo/fields/common/files/view_type/grid_item_component.html.erb +1 -1
  97. data/app/components/avo/fields/common/files/view_type/list_item_component.html.erb +7 -19
  98. data/app/components/avo/fields/common/heading_component.html.erb +2 -2
  99. data/app/components/avo/fields/common/heading_component.rb +1 -1
  100. data/app/components/avo/fields/common/key_value_component.html.erb +20 -24
  101. data/app/components/avo/fields/common/nested_field_component.html.erb +1 -1
  102. data/app/components/avo/fields/common/nested_field_component.rb +1 -1
  103. data/app/components/avo/fields/common/progress_bar_component.html.erb +2 -2
  104. data/app/components/avo/fields/common/stars_component.html.erb +1 -1
  105. data/app/components/avo/fields/common/status_viewer_component.html.erb +4 -10
  106. data/app/components/avo/fields/date_field/edit_component.html.erb +14 -1
  107. data/app/components/avo/fields/date_time_field/edit_component.html.erb +3 -3
  108. data/app/components/avo/fields/easy_mde_field/show_component.html.erb +1 -1
  109. data/app/components/avo/fields/edit_component.rb +9 -5
  110. data/app/components/avo/fields/file_field/edit_component.html.erb +14 -6
  111. data/app/components/avo/fields/files_field/edit_component.html.erb +11 -4
  112. data/app/components/avo/fields/has_one_field/show_component.html.erb +10 -9
  113. data/app/components/avo/fields/heading_field/edit_component.html.erb +1 -1
  114. data/app/components/avo/fields/heading_field/show_component.html.erb +2 -2
  115. data/app/components/avo/fields/password_field/edit_component.html.erb +5 -7
  116. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -1
  117. data/app/components/avo/fields/radio_field/edit_component.html.erb +1 -1
  118. data/app/components/avo/fields/show_component.rb +4 -7
  119. data/app/components/avo/fields/stars_field/edit_component.html.erb +3 -4
  120. data/app/components/avo/fields/tags_field/edit_component.html.erb +1 -1
  121. data/app/components/avo/fields/tags_field/tag_component.html.erb +7 -8
  122. data/app/components/avo/fields/time_field/edit_component.html.erb +3 -3
  123. data/app/components/avo/fields/tiptap_field/edit_component.html.erb +11 -11
  124. data/app/components/avo/fields/tiptap_field/show_component.html.erb +4 -4
  125. data/app/components/avo/fields/trix_field/edit_component.html.erb +2 -2
  126. data/app/components/avo/filters_component.html.erb +8 -16
  127. data/app/components/avo/index/field_wrapper_component.html.erb +9 -2
  128. data/app/components/avo/index/field_wrapper_component.rb +0 -16
  129. data/app/components/avo/index/grid_cover_empty_state_component.html.erb +2 -2
  130. data/app/components/avo/index/grid_item_component.html.erb +29 -12
  131. data/app/components/avo/index/grid_item_component.rb +12 -10
  132. data/app/components/avo/index/resource_controls_component.html.erb +1 -1
  133. data/app/components/avo/index/resource_controls_component.rb +7 -17
  134. data/app/components/avo/index/resource_controls_dropdown_component.html.erb +3 -0
  135. data/app/components/avo/index/resource_controls_dropdown_component.rb +81 -0
  136. data/app/components/avo/index/table_row_component.html.erb +11 -11
  137. data/app/components/avo/items/panel_component.html.erb +8 -18
  138. data/app/components/avo/items/panel_component.rb +0 -20
  139. data/app/components/avo/items/switcher_component.html.erb +62 -1
  140. data/app/components/avo/items/switcher_component.rb +10 -5
  141. data/app/components/avo/items/visible_items_component.html.erb +2 -1
  142. data/app/components/avo/items/visible_items_component.rb +1 -0
  143. data/app/components/avo/media_library/item_details_component.html.erb +2 -2
  144. data/app/components/avo/media_library/list_component.html.erb +24 -19
  145. data/app/components/avo/media_library/list_component.rb +2 -2
  146. data/app/components/avo/media_library/list_item_component.html.erb +3 -3
  147. data/app/components/avo/modal_component.html.erb +52 -20
  148. data/app/components/avo/modal_component.rb +7 -12
  149. data/app/components/avo/paginator_component.html.erb +46 -33
  150. data/app/components/avo/paginator_component.rb +10 -5
  151. data/app/components/avo/panel_name_component.html.erb +1 -1
  152. data/app/components/avo/profile_item_component.html.erb +4 -4
  153. data/app/components/avo/profile_item_component.rb +2 -4
  154. data/app/components/avo/referrer_params_component.html.erb +1 -1
  155. data/app/components/avo/resource_component.rb +8 -19
  156. data/app/components/avo/resource_listing_component.html.erb +22 -0
  157. data/app/components/avo/resource_listing_component.rb +28 -0
  158. data/app/components/avo/resource_sidebar_component.html.erb +2 -2
  159. data/app/components/avo/resource_sidebar_component.rb +0 -4
  160. data/app/components/avo/row_component.html.erb +1 -1
  161. data/app/components/avo/row_selector_component.html.erb +2 -4
  162. data/app/components/avo/row_selector_component.rb +0 -1
  163. data/app/components/avo/search_overlay_component.html.erb +6 -0
  164. data/app/components/avo/search_overlay_component.rb +2 -0
  165. data/app/components/avo/sidebar/base_item_component.rb +9 -9
  166. data/app/components/avo/sidebar/group_component.html.erb +23 -27
  167. data/app/components/avo/sidebar/group_component.rb +4 -0
  168. data/app/components/avo/sidebar/link_component.html.erb +30 -7
  169. data/app/components/avo/sidebar/link_component.rb +30 -2
  170. data/app/components/avo/sidebar/section_component.html.erb +31 -11
  171. data/app/components/avo/sidebar/section_component.rb +1 -3
  172. data/app/components/avo/sidebar_component.html.erb +35 -36
  173. data/app/components/avo/sidebar_component.rb +16 -0
  174. data/app/components/avo/sidebar_profile_component.html.erb +27 -36
  175. data/app/components/avo/sidebar_profile_component.rb +14 -0
  176. data/app/components/avo/tab_group_component.html.erb +21 -9
  177. data/app/components/avo/tab_group_component.rb +54 -15
  178. data/app/components/avo/turbo_frame_wrapper_component.html.erb +4 -8
  179. data/app/components/avo/turbo_frame_wrapper_component.rb +9 -0
  180. data/app/components/avo/u_i/avatar_component.html.erb +11 -0
  181. data/app/components/avo/u_i/avatar_component.rb +61 -0
  182. data/app/components/avo/u_i/badge_component.html.erb +9 -0
  183. data/app/components/avo/u_i/badge_component.rb +35 -0
  184. data/app/components/avo/u_i/card_component.html.erb +29 -0
  185. data/app/components/avo/u_i/card_component.rb +65 -0
  186. data/app/components/avo/u_i/dropdown_component.html.erb +14 -0
  187. data/app/components/avo/u_i/dropdown_component.rb +26 -0
  188. data/app/components/avo/u_i/dropdown_menu_component.html.erb +16 -0
  189. data/app/components/avo/u_i/dropdown_menu_component.rb +8 -0
  190. data/app/components/avo/u_i/file_upload_input_component.html.erb +26 -0
  191. data/app/components/avo/u_i/file_upload_input_component.rb +15 -0
  192. data/app/components/avo/u_i/file_upload_item_component.html.erb +48 -0
  193. data/app/components/avo/u_i/file_upload_item_component.rb +17 -0
  194. data/app/components/avo/u_i/icon_button_component.html.erb +7 -0
  195. data/app/components/avo/u_i/icon_button_component.rb +22 -0
  196. data/app/components/avo/u_i/panel_component.html.erb +49 -0
  197. data/app/components/avo/u_i/panel_component.rb +29 -0
  198. data/app/components/avo/u_i/panel_header_component.html.erb +37 -0
  199. data/app/components/avo/u_i/panel_header_component.rb +24 -0
  200. data/app/components/avo/u_i/search_input_component.html.erb +28 -0
  201. data/app/components/avo/u_i/search_input_component.rb +12 -0
  202. data/app/components/avo/u_i/tabs/tab_component.html.erb +26 -0
  203. data/app/components/avo/u_i/tabs/tab_component.rb +25 -0
  204. data/app/components/avo/u_i/tabs/tabs_component.html.erb +7 -0
  205. data/app/components/avo/u_i/tabs/tabs_component.rb +13 -0
  206. data/app/components/avo/view_types/base_view_type_component.rb +26 -0
  207. data/app/components/avo/view_types/grid_component.html.erb +18 -0
  208. data/app/components/avo/view_types/grid_component.rb +4 -0
  209. data/app/components/avo/view_types/map_component.html.erb +17 -0
  210. data/app/components/avo/view_types/map_component.rb +110 -0
  211. data/app/components/avo/view_types/table_component.html.erb +63 -0
  212. data/app/components/avo/{index/resource_table_component.rb → view_types/table_component.rb} +1 -10
  213. data/app/components/avo/views/resource_edit_component.html.erb +12 -18
  214. data/app/components/avo/views/resource_edit_component.rb +1 -27
  215. data/app/components/avo/views/resource_index_component.html.erb +97 -74
  216. data/app/components/avo/views/resource_index_component.rb +21 -1
  217. data/app/components/avo/views/resource_show_component.html.erb +4 -2
  218. data/app/components/avo/views/resource_show_component.rb +1 -4
  219. data/app/controllers/avo/associations_controller.rb +1 -1
  220. data/app/controllers/avo/base_application_controller.rb +7 -5
  221. data/app/controllers/avo/base_controller.rb +139 -40
  222. data/app/controllers/avo/debug_controller.rb +0 -29
  223. data/app/controllers/avo/media_library_controller.rb +17 -1
  224. data/app/controllers/avo/search_controller.rb +5 -0
  225. data/app/controllers/concerns/avo/initializes_avo.rb +7 -8
  226. data/app/helpers/avo/application_helper.rb +60 -46
  227. data/app/helpers/avo/turbo_stream_actions_helper.rb +10 -1
  228. data/app/helpers/avo/url_helpers.rb +3 -2
  229. data/app/javascript/{avo.base.js → application.js} +9 -18
  230. data/app/javascript/js/application.js +40 -0
  231. data/app/javascript/js/controllers/action_controller.js +4 -4
  232. data/app/javascript/js/controllers/actions_overflow_controller.js +21 -6
  233. data/app/javascript/js/controllers/color_scheme_switcher_controller.js +226 -0
  234. data/app/javascript/js/controllers/dropdown_menu_controller.js +42 -0
  235. data/app/javascript/js/controllers/fields/code_field_controller.js +20 -3
  236. data/app/javascript/js/controllers/fields/easy_mde_controller.js +23 -1
  237. data/app/javascript/js/controllers/fields/key_value_controller.js +43 -39
  238. data/app/javascript/js/controllers/fields/panel_refresh_controller.js +4 -0
  239. data/app/javascript/js/controllers/fields/tags_field_controller.js +2 -2
  240. data/app/javascript/js/controllers/fields/tags_field_helpers.js +4 -6
  241. data/app/javascript/js/controllers/item_selector_controller.js +0 -2
  242. data/app/javascript/js/controllers/loading_button_controller.js +1 -5
  243. data/app/javascript/js/controllers/map_dark_mode_controller.js +131 -0
  244. data/app/javascript/js/controllers/menu_controller.js +38 -16
  245. data/app/javascript/js/controllers/modal_controller.js +16 -0
  246. data/app/javascript/js/controllers/modal_size_controller.js +83 -0
  247. data/app/javascript/js/controllers/nested_form_controller.js +2 -2
  248. data/app/javascript/js/controllers/password_visibility_controller.js +13 -0
  249. data/app/javascript/js/controllers/preview_controller.js +2 -2
  250. data/app/javascript/js/controllers/resource_search_controller.js +123 -0
  251. data/app/javascript/js/controllers/search_controller.js +10 -29
  252. data/app/javascript/js/controllers/sidebar_controller.js +29 -9
  253. data/app/javascript/js/controllers/table_row_controller.js +28 -0
  254. data/app/javascript/js/controllers/tippy_controller.js +1 -1
  255. data/app/javascript/js/controllers/toggle_controller.js +40 -5
  256. data/app/javascript/js/controllers.js +12 -2
  257. data/app/javascript/js/custom-stream-actions.js +10 -8
  258. data/app/views/avo/actions/show.html.erb +14 -10
  259. data/app/views/avo/base/_boolean_filter.html.erb +1 -1
  260. data/app/views/avo/base/_date_time_filter.html.erb +3 -3
  261. data/app/views/avo/base/_multiple_select_filter.html.erb +1 -1
  262. data/app/views/avo/base/_new_via_belongs_to.html.erb +2 -3
  263. data/app/views/avo/base/_text_filter.html.erb +1 -1
  264. data/app/views/avo/base/preview.html.erb +5 -4
  265. data/app/views/avo/debug/status.html.erb +5 -92
  266. data/app/views/avo/debug/status.text.erb +0 -2
  267. data/app/views/avo/home/_actions.html.erb +1 -1
  268. data/app/views/avo/home/_dashboards.html.erb +1 -1
  269. data/app/views/avo/home/_filters.html.erb +1 -1
  270. data/app/views/avo/home/_resources.html.erb +2 -2
  271. data/app/views/avo/home/failed_to_load.html.erb +2 -2
  272. data/app/views/avo/home/index.html.erb +25 -25
  273. data/app/views/avo/media_library/_form.html.erb +43 -28
  274. data/app/views/avo/media_library/show.html.erb +7 -3
  275. data/app/views/avo/modal/_size_selector.html.erb +46 -0
  276. data/app/views/avo/partials/_alerts.html.erb +1 -1
  277. data/app/views/avo/partials/_color_scheme_switcher.html.erb +106 -0
  278. data/app/views/avo/partials/_color_theme_override.html.erb +49 -0
  279. data/app/views/avo/partials/_confirm_dialog.html.erb +4 -4
  280. data/app/views/avo/partials/_custom_tools_alert.html.erb +6 -6
  281. data/app/views/avo/partials/_footer.html.erb +1 -1
  282. data/app/views/avo/partials/_header.html.erb +1 -1
  283. data/app/views/avo/partials/_javascript.html.erb +0 -2
  284. data/app/views/avo/partials/_navbar.html.erb +53 -8
  285. data/app/views/avo/partials/_sortable_component.html.erb +1 -1
  286. data/app/views/avo/partials/_table_header.html.erb +28 -19
  287. data/app/views/avo/partials/_view_toggle_button.html.erb +6 -29
  288. data/app/views/avo/partials/distribution_chart.html.erb +2 -2
  289. data/app/views/avo/private/_links_and_buttons.html.erb +12 -8
  290. data/app/views/avo/private/design.html.erb +8 -4
  291. data/app/views/avo/sidebar/_license_warning.html.erb +3 -3
  292. data/app/views/layouts/avo/application.html.erb +39 -17
  293. data/app/views/layouts/avo/modal.html.erb +7 -0
  294. data/avo.gemspec +3 -4
  295. data/config/i18n-tasks.yml +1 -1
  296. data/config/importmap.rb +1 -0
  297. data/config/initializers/pagy.rb +5 -25
  298. data/config/routes/dynamic_routes.rb +4 -0
  299. data/config/routes.rb +6 -7
  300. data/db/factories.rb +14 -0
  301. data/lib/avo/asset_manager.rb +2 -0
  302. data/lib/avo/avatar.rb +7 -0
  303. data/lib/avo/base_action.rb +16 -4
  304. data/lib/avo/concerns/breadcrumbs.rb +7 -66
  305. data/lib/avo/concerns/form_builder.rb +41 -0
  306. data/lib/avo/concerns/{has_profile_photo.rb → has_avatar.rb} +8 -4
  307. data/lib/avo/concerns/{has_cover_photo.rb → has_cover.rb} +4 -4
  308. data/lib/avo/concerns/has_description.rb +9 -0
  309. data/lib/avo/concerns/has_item_type.rb +6 -2
  310. data/lib/avo/concerns/has_items.rb +43 -58
  311. data/lib/avo/concerns/pagination.rb +29 -19
  312. data/lib/avo/concerns/row_controls_configuration.rb +22 -15
  313. data/lib/avo/configuration/branding.rb +7 -7
  314. data/lib/avo/configuration.rb +92 -45
  315. data/lib/avo/{cover_photo.rb → cover.rb} +2 -2
  316. data/lib/avo/current.rb +0 -11
  317. data/lib/avo/discreet_information.rb +52 -29
  318. data/lib/avo/dsl/field_parser.rb +1 -1
  319. data/lib/avo/engine.rb +41 -8
  320. data/lib/avo/error_manager.rb +1 -1
  321. data/lib/avo/fields/avatar_field.rb +19 -0
  322. data/lib/avo/fields/badge_field.rb +23 -3
  323. data/lib/avo/fields/base_field.rb +46 -1
  324. data/lib/avo/fields/concerns/dom_id.rb +17 -0
  325. data/lib/avo/fields/concerns/file_authorization.rb +4 -0
  326. data/lib/avo/fields/concerns/has_html_attributes.rb +1 -1
  327. data/lib/avo/fields/concerns/is_searchable.rb +2 -5
  328. data/lib/avo/fields/concerns/nested.rb +1 -1
  329. data/lib/avo/fields/files_field.rb +2 -2
  330. data/lib/avo/fields/frame_base_field.rb +2 -2
  331. data/lib/avo/fields/id_field.rb +5 -1
  332. data/lib/avo/fields/progress_bar_field.rb +1 -1
  333. data/lib/avo/fields/text_field.rb +1 -1
  334. data/lib/avo/plugin_manager.rb +4 -0
  335. data/lib/avo/resources/base.rb +33 -21
  336. data/lib/avo/resources/controls/actions_list.rb +3 -3
  337. data/lib/avo/resources/controls/base_control.rb +1 -1
  338. data/lib/avo/resources/items/card.rb +16 -0
  339. data/lib/avo/resources/items/header.rb +11 -0
  340. data/lib/avo/resources/items/holder.rb +18 -23
  341. data/lib/avo/resources/items/item_group.rb +5 -7
  342. data/lib/avo/resources/items/sidebar.rb +5 -9
  343. data/lib/avo/resources/items/tab.rb +8 -8
  344. data/lib/avo/resources/items/tab_group.rb +8 -10
  345. data/lib/avo/resources/resource_manager.rb +2 -1
  346. data/lib/avo/services/hq_reporter.rb +102 -0
  347. data/lib/avo/services/telemetry_service.rb +0 -1
  348. data/lib/avo/test_helpers.rb +36 -22
  349. data/lib/avo/u_i_instance.rb +60 -0
  350. data/lib/avo/version.rb +1 -1
  351. data/lib/avo/view_inquirer.rb +6 -1
  352. data/lib/avo/view_types/view_type_manager.rb +70 -0
  353. data/lib/avo.rb +30 -45
  354. data/lib/generators/avo/action_generator.rb +1 -1
  355. data/lib/generators/avo/resource_generator.rb +43 -0
  356. data/lib/generators/avo/resource_tool_generator.rb +1 -1
  357. data/lib/generators/avo/tailwindcss/install_generator.rb +0 -6
  358. data/lib/generators/avo/templates/cards/partial_card_partial.tt +1 -1
  359. data/lib/generators/avo/templates/initializer/avo.tt +7 -9
  360. data/lib/generators/avo/templates/locales/avo.ar.yml +25 -0
  361. data/lib/generators/avo/templates/locales/avo.de.yml +25 -0
  362. data/lib/generators/avo/templates/locales/avo.en.yml +25 -0
  363. data/lib/generators/avo/templates/locales/avo.es.yml +25 -0
  364. data/lib/generators/avo/templates/locales/avo.fr.yml +25 -0
  365. data/lib/generators/avo/templates/locales/avo.it.yml +25 -0
  366. data/lib/generators/avo/templates/locales/avo.ja.yml +25 -0
  367. data/lib/generators/avo/templates/locales/avo.nb.yml +25 -0
  368. data/lib/generators/avo/templates/locales/avo.nl.yml +25 -0
  369. data/lib/generators/avo/templates/locales/avo.nn.yml +25 -0
  370. data/lib/generators/avo/templates/locales/avo.pl.yml +25 -0
  371. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +25 -0
  372. data/lib/generators/avo/templates/locales/avo.pt.yml +25 -0
  373. data/lib/generators/avo/templates/locales/avo.ro.yml +25 -0
  374. data/lib/generators/avo/templates/locales/avo.ru.yml +25 -0
  375. data/lib/generators/avo/templates/locales/avo.tr.yml +25 -0
  376. data/lib/generators/avo/templates/locales/{avo.uk.yml → avo.ua.yml} +26 -1
  377. data/lib/generators/avo/templates/locales/avo.zh-TW.yml +25 -0
  378. data/lib/generators/avo/templates/locales/avo.zh.yml +25 -0
  379. data/lib/generators/avo/templates/resource/resource.tt +10 -1
  380. data/lib/generators/avo/templates/resource_tools/partial.tt +20 -22
  381. data/lib/generators/avo/templates/tailwindcss/avo.tailwind.css +1 -3
  382. data/lib/generators/avo/templates/tailwindcss/tailwind.config.js +0 -7
  383. data/lib/generators/avo/templates/tool/view.tt +14 -16
  384. data/lib/generators/avo/tool_generator.rb +3 -3
  385. data/lib/generators/avo/version_generator.rb +1 -1
  386. data/lib/tasks/avo_tasks.rake +29 -25
  387. metadata +144 -97
  388. data/app/assets/stylesheets/avo.base.css +0 -130
  389. data/app/assets/stylesheets/css/breadcrumbs.css +0 -16
  390. data/app/assets/stylesheets/css/buttons.css +0 -19
  391. data/app/assets/stylesheets/css/tailwindcss/base.css +0 -1
  392. data/app/assets/stylesheets/css/tailwindcss/components.css +0 -1
  393. data/app/assets/stylesheets/css/tailwindcss/utilities.css +0 -1
  394. data/app/assets/svgs/avo/arrow-down.svg +0 -3
  395. data/app/assets/svgs/avo/arrow-up.svg +0 -3
  396. data/app/assets/svgs/avo/detach.svg +0 -8
  397. data/app/assets/svgs/avo/download-solid-reversed.svg +0 -3
  398. data/app/assets/svgs/avo/download-solid.svg +0 -3
  399. data/app/assets/svgs/avo/edit.svg +0 -5
  400. data/app/assets/svgs/avo/editor-bold.svg +0 -1
  401. data/app/assets/svgs/avo/editor-italic.svg +0 -1
  402. data/app/assets/svgs/avo/editor-link.svg +0 -1
  403. data/app/assets/svgs/avo/editor-list.svg +0 -1
  404. data/app/assets/svgs/avo/editor-strike.svg +0 -1
  405. data/app/assets/svgs/avo/editor-underline.svg +0 -1
  406. data/app/assets/svgs/avo/eye.svg +0 -1
  407. data/app/assets/svgs/avo/trash-sm.svg +0 -3
  408. data/app/assets/svgs/avo/trash.svg +0 -7
  409. data/app/components/avo/cover_photo_component.html.erb +0 -3
  410. data/app/components/avo/cover_photo_component.rb +0 -19
  411. data/app/components/avo/fields/common/badge_viewer_component.html.erb +0 -1
  412. data/app/components/avo/fields/common/badge_viewer_component.rb +0 -33
  413. data/app/components/avo/index/resource_grid_component.html.erb +0 -23
  414. data/app/components/avo/index/resource_grid_component.rb +0 -10
  415. data/app/components/avo/index/resource_map_component.html.erb +0 -16
  416. data/app/components/avo/index/resource_map_component.rb +0 -114
  417. data/app/components/avo/index/resource_table_component.html.erb +0 -52
  418. data/app/components/avo/panel_component.html.erb +0 -63
  419. data/app/components/avo/panel_component.rb +0 -43
  420. data/app/components/avo/panel_header_component.html.erb +0 -42
  421. data/app/components/avo/panel_header_component.rb +0 -31
  422. data/app/components/avo/profile_photo_component.html.erb +0 -6
  423. data/app/components/avo/profile_photo_component.rb +0 -9
  424. data/app/components/avo/sidebar/heading_component.html.erb +0 -21
  425. data/app/components/avo/sidebar/heading_component.rb +0 -9
  426. data/app/components/avo/tab_switcher_component.html.erb +0 -20
  427. data/app/components/avo/tab_switcher_component.rb +0 -45
  428. data/app/views/avo/base/close_modal_and_reload_field.turbo_stream.erb +0 -8
  429. data/app/views/avo/debug/report.html.erb +0 -37
  430. data/app/views/avo/partials/_panel_breadcrumbs.html.erb +0 -3
  431. data/app/views/avo/partials/_resource_search.html.erb +0 -16
  432. data/lib/avo/licensing/community_license.rb +0 -6
  433. data/lib/avo/licensing/h_q.rb +0 -202
  434. data/lib/avo/licensing/license.rb +0 -76
  435. data/lib/avo/licensing/license_manager.rb +0 -24
  436. data/lib/avo/licensing/nil_license.rb +0 -14
  437. data/lib/avo/licensing/pro_license.rb +0 -20
  438. data/lib/avo/licensing/request.rb +0 -20
  439. data/lib/avo/profile_photo.rb +0 -7
  440. data/lib/avo/services/debug_service.rb +0 -107
  441. data/tailwind.preset.js +0 -171
  442. /data/{public/avo-assets → app/assets/images/avo}/favicon.ico +0 -0
  443. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.eot +0 -0
  444. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.svg +0 -0
  445. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.ttf +0 -0
  446. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.woff +0 -0
  447. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-500.woff2 +0 -0
  448. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.eot +0 -0
  449. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.svg +0 -0
  450. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.ttf +0 -0
  451. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.woff +0 -0
  452. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-600.woff2 +0 -0
  453. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.eot +0 -0
  454. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.svg +0 -0
  455. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.ttf +0 -0
  456. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.woff +0 -0
  457. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-700.woff2 +0 -0
  458. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.eot +0 -0
  459. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.svg +0 -0
  460. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.ttf +0 -0
  461. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.woff +0 -0
  462. /data/{public/avo-assets → app/assets/images/avo}/fonts/inter-v7-latin-regular.woff2 +0 -0
  463. /data/{public/avo-assets → app/assets/images/avo}/logo-on-white.png +0 -0
  464. /data/{public/avo-assets → app/assets/images/avo}/logo.png +0 -0
  465. /data/{public/avo-assets → app/assets/images/avo}/logomark.png +0 -0
  466. /data/{public/avo-assets → app/assets/images/avo}/placeholder.svg +0 -0
@@ -1,38 +1,51 @@
1
- <div class="flex flex-col sm:flex-row items-center justify-between aborder-t aborder-slate-200 rounded-2xl space-y-2 sm:space-y-0">
2
- <div class="flex-2 sm:flex sm:items-center sm:justify-between">
3
- <div>
4
- <div class="text-sm leading-5 text-slate-600 flex items-center">
5
- <div data-controller="per-page">
6
- <div class="flex items-center">
7
- <%= content_tag :label, name: t('avo.per_page').downcase do %>
8
- <%= select_tag 'per_page',
9
- options_for_select(per_page_options, @index_params[:per_page]),
10
- class: 'appearance-none inline-flex bg-white-100 disabled:bg-white-400 disabled:cursor-not-allowed focus:bg-white text-slate-700 disabled:text-slate-600 rounded-md py-1 px-2 leading-tight border border-slate-300 outline-none focus:border-slate-400 outline w-16 mr-1 text-sm',
11
- data: {
12
- 'turbo-frame': @turbo_frame,
13
- 'per-page-target': 'selector',
14
- action: 'change->per-page#reload'
15
- }
16
- %> <%= t('avo.per_page').downcase %>
17
- <% end %>
18
- </div>
19
- <% per_page_options.each do |option| %>
20
- <%= link_to "Change to #{option} items per page", change_items_per_page_url(option), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': @turbo_frame %>
1
+ <div class="pagination">
2
+ <%# Left: per-page selector %>
3
+ <div class="pagination__per-page">
4
+ <%= render ui.dropdown(classes: "start-0 end-auto") do |component| %>
5
+ <% component.with_trigger do %>
6
+ <button
7
+ type="button"
8
+ class="pagination__per-page-input"
9
+ data-action="<%= component.action %>"
10
+ aria-haspopup="listbox"
11
+ aria-expanded="false"
12
+ >
13
+ <span class="pagination__per-page-value"><%== current_per_page_label %></span>
14
+ <span class="pagination__per-page-icon" aria-hidden="true">
15
+ <%= helpers.svg "tabler/outline/chevron-down" %>
16
+ </span>
17
+ </button>
18
+ <% end %>
19
+ <% component.with_items do %>
20
+ <% per_page_options.each do |option| %>
21
+ <%= link_to change_items_per_page_url(option),
22
+ class: "dropdown-menu__item",
23
+ data: { turbo_frame: @turbo_frame } do %>
24
+ <%== per_page_option_label(option) %>
21
25
  <% end %>
22
- </div>
23
- </div>
24
- </div>
25
- </div>
26
- <div class="flex">
27
- <div class="flex-2 sm:flex sm:items-center sm:justify-between space-y-2 sm:space-y-0 text-center sm:text-left pagy-gem-version-<%= helpers.pagy_major_version %>">
28
- <% if @resource.pagination_type.default? %>
29
- <div class="text-sm text-slate-600 mr-4"><%== helpers.pagy_info @pagy %></div>
26
+ <% end %>
30
27
  <% end %>
28
+ <% end %>
29
+ </div>
31
30
 
32
- <% if @pagy.pages > 1 %>
33
- <%# @todo: add first & last page. make the first and last buttons rounded %>
34
- <%== helpers.pagy_nav @pagy, anchor_string: "data-turbo-frame=\"#{@turbo_frame}\"" %>
35
- <% end %>
36
- </div>
31
+ <%# Right: info + navigation grouped pill %>
32
+ <div class="pagination__controls">
33
+ <% if @resource.pagination_type.default? %>
34
+ <div class="pagination__info">
35
+ <span class="pagination__info-number">
36
+ <%= "#{@pagy.from}-#{@pagy.to}" %>
37
+ </span>
38
+ &nbsp; of &nbsp;
39
+ <span>
40
+ <%= "#{@pagy.count}" %>
41
+ </span>
42
+ </div>
43
+ <% end %>
44
+
45
+ <% if @pagy.pages > 1 %>
46
+ <div class="pagination__nav">
47
+ <%== @pagy.series_nav(anchor_string: "data-turbo-frame=\"#{@turbo_frame}\"") %>
48
+ </div>
49
+ <% end %>
37
50
  </div>
38
51
  </div>
@@ -29,11 +29,7 @@ class Avo::PaginatorComponent < Avo::BaseComponent
29
29
  def render?
30
30
  return false if @discreet_pagination && @pagy.pages <= 1
31
31
 
32
- if ::Pagy::VERSION >= ::Gem::Version.new("9.0")
33
- @pagy.limit > 0
34
- else
35
- @pagy.items > 0
36
- end
32
+ @pagy.limit > 0
37
33
  end
38
34
 
39
35
  def per_page_options
@@ -47,4 +43,13 @@ class Avo::PaginatorComponent < Avo::BaseComponent
47
43
  options.sort.uniq
48
44
  end
49
45
  end
46
+
47
+ def current_per_page_label
48
+ per_page_option_label(@index_params[:per_page])
49
+ end
50
+
51
+ def per_page_option_label(option)
52
+ num = helpers.content_tag(:span, option, class: "pagination__per-page-option-num")
53
+ "#{num} #{t("avo.per_page").downcase}".html_safe
54
+ end
50
55
  end
@@ -1,4 +1,4 @@
1
- <div class="text-2xl tracking-normal font-semibold text-gray-800 items-center flex flex-1 text-center sm:text-left justify-center sm:justify-start" data-target="title">
1
+ <div class="text-2xl tracking-normal font-semibold text-gray-800 items-center flex flex-1 text-center sm:text-start justify-center sm:justify-start" data-target="title">
2
2
  <span class="block"><%= link_to_if @url.present?, @name, @url, target: @target, class: class_names("text-gray-800", @classes) %></span>
3
3
  <%= body %>
4
4
  </div>
@@ -1,19 +1,19 @@
1
1
  <% if method.present? %>
2
2
  <%= button_to path,
3
3
  form_class: "flex-1 flex",
4
- class: button_classes,
4
+ class: menu_item_classes,
5
5
  target: target,
6
6
  title: title,
7
7
  method: method,
8
8
  disabled: disabled,
9
9
  params: params do %>
10
- <%= helpers.svg(icon, class: 'h-4 mr-1') if icon.present? %> <%= label %>
10
+ <%= helpers.svg(icon, class: 'sidebar-icon') if icon.present? %> <%= label %>
11
11
  <% end %>
12
12
  <% else %>
13
13
  <%= link_to path,
14
- class: button_classes,
14
+ class: menu_item_classes,
15
15
  target: target,
16
16
  title: title do %>
17
- <%= helpers.svg(icon, class: 'h-4 mr-1') if icon.present? %> <%= label %>
17
+ <%= helpers.svg(icon, class: 'sidebar-icon') if icon.present? %> <%= label %>
18
18
  <% end %>
19
19
  <% end %>
@@ -20,9 +20,7 @@ class Avo::ProfileItemComponent < Avo::BaseComponent
20
20
  @title || @label
21
21
  end
22
22
 
23
- private
24
-
25
- def button_classes
26
- "flex-1 flex items-center justify-center bg-white text-left cursor-pointer text-gray-800 font-semibold hover:bg-primary-100 block px-4 py-1 w-full py-3 text-center rounded w-full"
23
+ def menu_item_classes
24
+ "sidebar-profile__menu-item #{classes}".strip
27
25
  end
28
26
  end
@@ -4,5 +4,5 @@
4
4
  <%= hidden_field_tag :via_record_id, params[:via_record_id] if params[:via_record_id] %>
5
5
  <%= hidden_field_tag :via_relation, params[:via_relation] if params[:via_relation] %>
6
6
  <%= hidden_field_tag :via_belongs_to_resource_class, params[:via_belongs_to_resource_class] if params[:via_belongs_to_resource_class] %>
7
- <%= hidden_field_tag :return_to, e(params[:return_to]) if params[:return_to].present? %>
7
+ <%= hidden_field_tag :return_to, params[:return_to] if params[:return_to].present? %>
8
8
  <%= hidden_field_tag :referrer, @back_path if params[:via_resource_class] %>
@@ -75,15 +75,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
75
75
  helpers.resource_path(**args)
76
76
  end
77
77
 
78
- def main_panel
79
- @main_panel ||= @resource.get_items.find do |item|
80
- item.is_main_panel?
81
- end
82
- end
83
-
84
78
  def sidebars
85
- return [] if Avo.license.lacks_with_trial(:resource_sidebar)
86
-
87
79
  @sidebars ||= @item.items
88
80
  .select do |item|
89
81
  item.is_sidebar?
@@ -161,8 +153,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
161
153
  a_link destroy_path,
162
154
  style: :text,
163
155
  color: :red,
164
- icon: "avo/trash",
165
- form_class: "flex flex-col sm:flex-row sm:inline-flex",
156
+ icon: "tabler/outline/trash",
166
157
  title: control.title,
167
158
  aria_label: control.title,
168
159
  data: {
@@ -186,7 +177,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
186
177
 
187
178
  add_stimulus_attributes_for(@resource, data_attributes, "saveButton")
188
179
 
189
- a_button color: :primary,
180
+ a_button color: :accent,
190
181
  style: :primary,
191
182
  loading: true,
192
183
  type: :submit,
@@ -200,11 +191,11 @@ class Avo::ResourceComponent < Avo::BaseComponent
200
191
  return unless can_see_the_edit_button?
201
192
 
202
193
  a_link edit_path,
203
- color: :primary,
194
+ color: :accent,
204
195
  style: :primary,
205
196
  title: control.title,
206
197
  data: {tippy: control.title ? :tooltip : nil},
207
- icon: "avo/edit" do
198
+ icon: "tabler/outline/edit" do
208
199
  control.label
209
200
  end
210
201
  end
@@ -213,8 +204,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
213
204
  return unless is_a_related_resource? && can_detach?
214
205
 
215
206
  a_link detach_path,
216
- icon: "avo/detach",
217
- form_class: "flex flex-col sm:flex-row sm:inline-flex",
207
+ icon: "tabler/outline/unlink",
218
208
  style: :text,
219
209
  data: {
220
210
  turbo_method: :delete,
@@ -228,9 +218,9 @@ class Avo::ResourceComponent < Avo::BaseComponent
228
218
  return unless can_see_the_create_button?
229
219
 
230
220
  a_link create_path,
231
- color: :primary,
221
+ color: :accent,
232
222
  style: :primary,
233
- icon: "heroicons/outline/plus",
223
+ icon: "tabler/outline/plus",
234
224
  data: {
235
225
  target: :create
236
226
  } do
@@ -242,8 +232,7 @@ class Avo::ResourceComponent < Avo::BaseComponent
242
232
  return unless can_attach?
243
233
 
244
234
  a_link attach_path,
245
- icon: "heroicons/outline/link",
246
- color: :primary,
235
+ icon: "tabler/outline/link",
247
236
  style: :text,
248
237
  data: {
249
238
  turbo_frame: Avo::MODAL_FRAME_ID,
@@ -0,0 +1,22 @@
1
+ <%= content_tag :div, id: "#{@resource.model_key}_body_content" do %>
2
+ <%= render Avo::SearchOverlayComponent.new %>
3
+
4
+ <% if @resources.present? %>
5
+ <div class="relative mt-0 flex w-full flex-1">
6
+ <%= render(@resource.resolve_component(specific_view_component).new(
7
+ resources: @resources,
8
+ resource: @resource,
9
+ reflection: @reflection,
10
+ parent_record: @parent_record,
11
+ parent_resource: @parent_resource,
12
+ pagy: @pagy,
13
+ query: @query,
14
+ actions: @actions,
15
+ turbo_frame: @turbo_frame,
16
+ index_params: @index_params
17
+ )) %>
18
+ </div>
19
+ <% else %>
20
+ <%= helpers.empty_state by_association: params[:related_name].present? %>
21
+ <% end %>
22
+ <% end %>
@@ -0,0 +1,28 @@
1
+ class Avo::ResourceListingComponent < Avo::BaseComponent
2
+ prop :resources
3
+ prop :resource
4
+ prop :reflection
5
+ prop :parent_record
6
+ prop :parent_resource
7
+ prop :pagy
8
+ prop :query
9
+ prop :actions
10
+ prop :turbo_frame
11
+ prop :index_params
12
+
13
+ def specific_view_component
14
+ Avo.view_type_manager.component_for(@resource.view_type)
15
+ end
16
+
17
+ def paginator_component
18
+ Avo::PaginatorComponent.new(
19
+ pagy: @pagy,
20
+ turbo_frame: @turbo_frame,
21
+ index_params: @index_params,
22
+ resource: @resource,
23
+ parent_record: @parent_record,
24
+ parent_resource: @parent_resource,
25
+ discreet_pagination: field&.discreet_pagination
26
+ )
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
- <div class="resource-sidebar-component divide-y"
1
+ <div class="resource-sidebar-component space-y-4"
2
2
  data-component-name="<%= self.class.to_s.underscore %>"
3
3
  data-component-index="<%= @index %>"
4
4
  data-resource-name="<%= @resource.class.to_s %>"
@@ -12,5 +12,5 @@
12
12
  field_component_extra_args: {
13
13
  stacked: true
14
14
  }
15
- )%>
15
+ ) %>
16
16
  </div>
@@ -7,8 +7,4 @@ class Avo::ResourceSidebarComponent < Avo::BaseComponent
7
7
  prop :params
8
8
  prop :form
9
9
  prop :view, reader: :public
10
-
11
- def render?
12
- Avo.license.has_with_trial(:resource_sidebar)
13
- end
14
10
  end
@@ -6,7 +6,7 @@
6
6
  }
7
7
  ),
8
8
  data: {
9
- component: self.class.to_s
9
+ component_name:
10
10
  } do %>
11
11
  <%= body %>
12
12
  <% end %>
@@ -6,10 +6,8 @@
6
6
  title: t("avo.select_item"),
7
7
  autocomplete: :off,
8
8
  checked: @checked,
9
- class: class_names("mx-3 rounded checked:bg-primary-400 focus:checked:!bg-primary-400", {
10
- "absolute inset-auto left-0 mt-3 z-10 hidden group-hover:block checked:block": @floating,
11
- "w-5 h-5": @size.to_sym == :lg,
12
- "w-4 h-4": @size.to_sym != :lg,
9
+ class: class_names("mx-2", {
10
+ "absolute block start-0 top-0 mt-3 z-10 hidden": @floating,
13
11
  }),
14
12
  data: {
15
13
  index: @index,
@@ -2,7 +2,6 @@
2
2
 
3
3
  class Avo::RowSelectorComponent < Avo::BaseComponent
4
4
  prop :floating, default: false
5
- prop :size, default: :md
6
5
  prop :index
7
6
  prop :checked, default: false
8
7
 
@@ -0,0 +1,6 @@
1
+ <div class="avo-search-overlay" data-resource-search-target="overlay">
2
+ <div class="button-spinner">
3
+ <div class="double-bounce1"></div>
4
+ <div class="double-bounce2"></div>
5
+ </div>
6
+ </div>
@@ -0,0 +1,2 @@
1
+ class Avo::SearchOverlayComponent < Avo::BaseComponent
2
+ end
@@ -24,14 +24,14 @@ class Avo::Sidebar::BaseItemComponent < Avo::BaseComponent
24
24
  result
25
25
  end
26
26
 
27
- def section_collapse_data_animation
28
- {
29
- transition_enter: "transition ease-out duration-100",
30
- transition_enter_start: "transform opacity-0 -translate-y-4",
31
- transition_enter_end: "transform opacity-100 translate-y-0",
32
- transition_leave: "transition ease-in duration-75",
33
- transition_leave_start: "transform opacity-100 translate-y-0",
34
- transition_leave_end: "transform opacity-0 -translate-y-4",
35
- }
27
+ def data
28
+ result = {}
29
+ if collapsable
30
+ result[:controller] = "menu"
31
+ result[:menu_target] = "self"
32
+ result[:menu_key_param] = key
33
+ result[:menu_default_collapsed_state] = collapsed ? "collapsed" : "expanded"
34
+ end
35
+ result
36
36
  end
37
37
  end
@@ -1,43 +1,39 @@
1
- <div class="pb-2 space-y-1"
2
- <% if collapsable %>
3
- data-controller="menu"
4
- data-menu-target="self"
5
- data-menu-key-param="<%= key %>"
6
- data-menu-default-collapsed-state="<%= collapsed ? 'collapsed' : 'expanded' %>"
7
- <% end %>
8
- >
1
+ <%= tag.div class: "sidebar-group", data: data do %>
9
2
  <% if item.name.present? %>
10
3
  <% if collapsable %>
11
- <div
12
- class="flex justify-between cursor-pointer px-10 pr-2 pt-2 pb-0 text-gray-400"
4
+ <button
5
+ type="button"
6
+ class="sidebar-group__header justify-between"
13
7
  data-action="click->menu#triggerCollapse"
14
- data-menu-key-param="<%= key %>"
8
+ data-menu-target="trigger"
9
+ aria-expanded="<%= !collapsed %>"
15
10
  >
16
- <div class="flex items-center text-xs uppercase font-semibold leading-none">
17
- <%= item.name %>
11
+ <div class="sidebar-group__header-inner">
12
+ <span><%= item.name %></span>
18
13
  </div>
19
- <div class="<%= 'rotate-90' if collapsed %>"
14
+ <span class="sidebar-icon <%= 'sidebar-icon--collapsed' if collapsed %>"
20
15
  data-menu-target="svg"
21
- >
22
- <%= helpers.svg 'heroicons/outline/chevron-down', class: "h-4 mr-0.5"%>
23
- </div>
24
- </div>
16
+ >
17
+ <%= helpers.svg 'heroicons/outline/chevron-down', class: 'h-4' %>
18
+ </span>
19
+ </button>
25
20
  <% else %>
26
- <div class="flex justify-between px-10 pr-2 pt-2 pb-0 text-gray-400">
27
- <div class="flex items-center text-xs uppercase font-semibold leading-none">
28
- <%= item.name %>
29
- </div>
30
- </div>
21
+ <div class="sidebar-group__header">
22
+ <div class="sidebar-group__header-inner">
23
+ <span><%= item.name %></span>
24
+ </div>
25
+ </div>
31
26
  <% end %>
32
27
  <% end %>
33
28
 
34
- <%= content_tag :div, class: class_names("w-full space-y-1", {"hidden": collapsed}),
29
+ <%= content_tag :div,
30
+ hidden: collapsed,
31
+ class: "sidebar-group__items",
35
32
  data: {
36
33
  menu_target: :items,
37
- **section_collapse_data_animation
38
34
  } do %>
39
35
  <% @items.each do |item| %>
40
- <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
36
+ <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item, group_has_icons: group_has_any_icon? %>
41
37
  <% end %>
42
38
  <% end %>
43
- </div>
39
+ <% end %>
@@ -1,4 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Avo::Sidebar::GroupComponent < Avo::Sidebar::BaseItemComponent
4
+ # True if any visible item in the group has an icon (so all items should reserve icon space for alignment).
5
+ def group_has_any_icon?
6
+ @items.any? { |child| child.try(:icon).present? }
7
+ end
4
8
  end
@@ -1,14 +1,37 @@
1
1
  <% if @path.present? %>
2
- <%= link_caller.send link_method, @path, class: classes, active: @active, target: @target, data: @data, **@args do %>
3
- <%= helpers.svg @icon, class: "h-4 text-gray-700" if @icon.present? %>
4
- <%= @label %>
2
+ <%= link_caller.send link_method, @path, class: "sidebar-link", active: @active, target: @target, data: @data, disabled: @disabled, "aria-disabled": @disabled, **@args do %>
3
+ <% if @reserve_icon_space || link_icon.present? %>
4
+ <span class="sidebar-link__icon-wrapper sidebar-icon<%= ' sidebar-link__icon-wrapper--placeholder' if link_icon.blank? %>">
5
+ <%= helpers.svg link_icon, class: "sidebar-link__icon sidebar-icon" if link_icon.present? %>
6
+ </span>
7
+ <% end %>
8
+ <span><%= @label %></span>
5
9
  <% if @target == :_blank %>
6
- <%= helpers.svg('heroicons/outline/external-link', class: 'self-center ml-auto h-3 mr-2') %>
10
+ <%= helpers.svg("tabler/outline/external-link", class: "sidebar-link__external-icon sidebar-icon") %>
7
11
  <% end %>
8
12
  <% end %>
9
13
  <% else %>
10
- <%= content_tag :div, class: classes, active: @active, target: @target, data: @data do %>
11
- <%= helpers.svg @icon, class: "h-4 text-gray-700" if @icon.present? %>
12
- <%= @label %>
14
+ <%= content_tag :div, class: "sidebar-link", active: @active, target: @target, data: @data do %>
15
+ <% if @reserve_icon_space || link_icon.present? %>
16
+ <span class="sidebar-link__icon-wrapper sidebar-icon<%= ' sidebar-link__icon-wrapper--placeholder' if link_icon.blank? %>">
17
+ <%= helpers.svg link_icon, class: "sidebar-link__icon sidebar-icon" if link_icon.present? %>
18
+ </span>
19
+ <% end %>
20
+ <span><%= @label %></span>
13
21
  <% end %>
14
22
  <% end %>
23
+ <% if @items.present? && parent_link_active? %>
24
+ <div class="sidebar-subitem__items">
25
+ <% @items.each_with_index do |item, index| %>
26
+ <% if item.path.present? %>
27
+ <%= link_caller.send link_method, item.path, class: "sidebar-subitem #{subitem_bar_class(index)}", active: @active, target: item.target, data: item.data, disabled: @disabled, "aria-disabled": @disabled, **item.args do %>
28
+ <span><%= item.try(:label).presence || item.try(:name).presence %></span>
29
+ <% end %>
30
+ <% else %>
31
+ <%= content_tag :div, class: "sidebar-subitem #{subitem_bar_class(index)}", active: @active, target: item.target, data: item.data do %>
32
+ <span><%= item.try(:label).presence || item.try(:name).presence %></span>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
36
+ </div>
37
+ <% end %>
@@ -13,7 +13,9 @@ class Avo::Sidebar::LinkComponent < Avo::BaseComponent
13
13
  end
14
14
  prop :data, default: {}.freeze
15
15
  prop :icon
16
+ prop :reserve_icon_space, default: false
16
17
  prop :args, kind: :**, default: {}.freeze
18
+ prop :items
17
19
 
18
20
  def is_external?
19
21
  # If the path contains the scheme, check if it includes the root path or not
@@ -36,7 +38,33 @@ class Avo::Sidebar::LinkComponent < Avo::BaseComponent
36
38
  end
37
39
  end
38
40
 
39
- def classes
40
- "px-4 pr-0 flex-1 flex mx-6 leading-none py-2 text-black rounded font-medium hover:bg-gray-100 gap-1"
41
+ def parent_link_active?
42
+ return false if @path.blank?
43
+ helpers.is_active_link?(@path, @active)
44
+ end
45
+
46
+ def link_icon
47
+ @icon
48
+ end
49
+
50
+ def active_item_index
51
+ return @active_item_index if defined?(@active_item_index)
52
+
53
+ @active_item_index = @items&.index do |item|
54
+ item.path.present? && helpers.is_active_link?(item.path, @active)
55
+ end
56
+ end
57
+
58
+ def subitem_bar_class(index)
59
+ active_idx = active_item_index
60
+ return "" if active_idx.nil?
61
+
62
+ if index == active_idx
63
+ "sidebar-subitem--bar-active"
64
+ elsif index < active_idx
65
+ "sidebar-subitem--bar-pass"
66
+ else
67
+ ""
68
+ end
41
69
  end
42
70
  end
@@ -1,19 +1,39 @@
1
- <div class="space-y-1 mb-4"
2
- <% if collapsable %>
3
- data-controller="menu"
4
- data-menu-target="self"
5
- data-menu-key-param="<%= key %>"
6
- data-menu-default-collapsed-state="<%= collapsed ? 'collapsed' : 'expanded' %>"
1
+ <%= tag.div class: "sidebar-section", data: data do %>
2
+ <% if item.name.present? %>
3
+ <% if collapsable %>
4
+ <button
5
+ type="button"
6
+ class="sidebar-section__header justify-between"
7
+ data-action="click->menu#triggerCollapse"
8
+ data-menu-target="trigger"
9
+ aria-expanded="<%= !collapsed %>"
10
+ >
11
+ <div class="sidebar-section__header-inner">
12
+ <%= helpers.svg icon, class: "sidebar-section__icon sidebar-icon" if icon.present? %>
13
+ <span><%= item.name %></span>
14
+ </div>
15
+ <span class="sidebar-section__icon sidebar-icon <%= 'sidebar-icon--collapsed' if collapsed %>"
16
+ data-menu-target="svg"
17
+ >
18
+ <%= helpers.svg 'heroicons/outline/chevron-down' %>
19
+ </span>
20
+ </button>
21
+ <% else %>
22
+ <div class="sidebar-section__header">
23
+ <%= helpers.svg icon, class: "sidebar-section__icon sidebar-icon" if icon.present? %>
24
+ <span><%= item.name %></span>
25
+ </div>
26
+ <% end %>
7
27
  <% end %>
8
- >
9
- <%= render Avo::Sidebar::HeadingComponent.new label: item.name, icon: helpers.svg(icon, class: "h-5"), collapsable: item.collapsable, collapsed: collapsed, key: key %>
10
- <%= content_tag :div, class: class_names("w-full space-y-1", {"hidden": collapsed}),
28
+
29
+ <%= content_tag :div,
30
+ hidden: collapsed,
31
+ class: "sidebar-section__items",
11
32
  data: {
12
33
  menu_target: :items,
13
- **section_collapse_data_animation
14
34
  } do %>
15
35
  <% @items.each do |item| %>
16
36
  <%= render Avo::Sidebar::ItemSwitcherComponent.new item: item %>
17
37
  <% end %>
18
38
  <% end %>
19
- </div>
39
+ <% end %>
@@ -2,8 +2,6 @@
2
2
 
3
3
  class Avo::Sidebar::SectionComponent < Avo::Sidebar::BaseItemComponent
4
4
  def icon
5
- return nil if item.icon.nil?
6
-
7
- item.icon
5
+ item.icon if item.icon.present?
8
6
  end
9
7
  end