diff --git a/app/components/avo/asset_manager/javascript_component.html.erb b/app/components/avo/asset_manager/javascript_component.html.erb index 92ab565571..41439d7d39 100644 --- a/app/components/avo/asset_manager/javascript_component.html.erb +++ b/app/components/avo/asset_manager/javascript_component.html.erb @@ -1,3 +1,11 @@ <% javascripts.each do |path| %> <%= javascript_include_tag path, "data-turbo-track": "reload", defer: true %> <% end %> + +<%# Collect all the custom StimulusJS controllers from plugins. %> +<%= javascript_tag nonce: true do %> + Avo.configuration.stimulus_controllers = <%== Avo.asset_manager.stimulus_controllers.to_a.to_json %> +<% end %> + +<%# This is the last script to run so it can register custom StimulusJS controllers from plugins. %> +<%= javascript_include_tag 'late-registration', "data-turbo-track": "reload", defer: true %> diff --git a/app/components/avo/asset_manager/javascript_component.rb b/app/components/avo/asset_manager/javascript_component.rb index 3de1aa8ee9..b08e80da4a 100644 --- a/app/components/avo/asset_manager/javascript_component.rb +++ b/app/components/avo/asset_manager/javascript_component.rb @@ -4,4 +4,5 @@ class Avo::AssetManager::JavascriptComponent < Avo::BaseComponent prop :asset_manager delegate :javascripts, to: :@asset_manager + delegate :stimulus_controllers, to: :@asset_manager end diff --git a/app/javascript/avo.base.js b/app/javascript/avo.base.js index 0e36a174f9..8c3fb9491e 100644 --- a/app/javascript/avo.base.js +++ b/app/javascript/avo.base.js @@ -22,7 +22,7 @@ window.Turbolinks = Turbo let scrollTop = null Mousetrap.bind('r r r', () => { - // Cpture scroll position + // Capture scroll position scrollTop = document.scrollingElement.scrollTop Turbo.visit(window.location.href, { action: 'replace' }) diff --git a/app/javascript/js/application.js b/app/javascript/js/application.js index 986239cb83..b1f817d711 100644 --- a/app/javascript/js/application.js +++ b/app/javascript/js/application.js @@ -1,5 +1,5 @@ import { Alert, Popover } from 'tailwindcss-stimulus-components' -import { Application } from '@hotwired/stimulus' +import { Application, Controller } from '@hotwired/stimulus' import Clipboard from '@stimulus-components/clipboard' import PasswordVisibility from '@stimulus-components/password-visibility' import TextareaAutogrow from 'stimulus-textarea-autogrow' @@ -13,6 +13,22 @@ const application = Application.start() application.debug = window?.localStorage.getItem('avo.debug') window.Stimulus = application +/* Using this patter of providing a fake Stimulus object so the plugins do not have to bundle the Stimulus controller too. + Their rollup config is isntructed to use `fakeStimulus` instead of `Stimulus`. + output: { + ... + globals: { + "@hotwired/stimulus": "FakeStimulus" + } + } + + Example rollup config + https://github.com/avo-hq/marksmith/blob/main/rollup.config.mjs +*/ +window.FakeStimulus = { + Controller, +} + // Register stimulus-components controller application.register('alert', Alert) application.register('popover', Popover) diff --git a/app/javascript/late-registration.js b/app/javascript/late-registration.js new file mode 100644 index 0000000000..cda9bf934a --- /dev/null +++ b/app/javascript/late-registration.js @@ -0,0 +1,8 @@ +const application = window.Stimulus + +// This is going run last so it can regiser custom StimulusJS controllers from plugins. +if (window.Avo.configuration.stimulus_controllers) { + window.Avo.configuration.stimulus_controllers.forEach(([name, controller]) => { + application.register(name, window[controller]) + }) +} diff --git a/app/views/avo/partials/_javascript.html.erb b/app/views/avo/partials/_javascript.html.erb index 006bc03db1..7e8fc0fbfb 100644 --- a/app/views/avo/partials/_javascript.html.erb +++ b/app/views/avo/partials/_javascript.html.erb @@ -12,4 +12,5 @@ } <% end %> Avo.configuration.modal_frame_id = '<%= ::Avo::MODAL_FRAME_ID %>' + Avo.configuration.stimulus_controllers = [] <% end %> diff --git a/lib/avo/asset_manager.rb b/lib/avo/asset_manager.rb index c29334ce5a..57a5dacb29 100644 --- a/lib/avo/asset_manager.rb +++ b/lib/avo/asset_manager.rb @@ -2,14 +2,18 @@ module Avo class AssetManager include ActionView::Helpers::AssetTagHelper + attr_reader :stimulus_controllers + def initialize @stylesheets = [] @javascripts = [] + @stimulus_controllers = {} end def reset @stylesheets = [] @javascripts = [] + @stimulus_controllers = {} end def add_stylesheet(path) @@ -20,6 +24,10 @@ def add_javascript(path) @javascripts.push path end + def register_stimulus_controller(name, controller) + @stimulus_controllers[name] = controller + end + def stylesheets @stylesheets.uniq end