diff --git a/lib/inertia_rails_contrib/inertia_ui_modal.rb b/lib/inertia_rails_contrib/inertia_ui_modal.rb new file mode 100644 index 0000000..3d16d43 --- /dev/null +++ b/lib/inertia_rails_contrib/inertia_ui_modal.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require "inertia_rails/renderer" + +require_relative "inertia_ui_modal_renderer" + +InertiaRails::Renderer.prepend(Module.new do + def page + super.tap do |modal| + if @request.env[:_inertiaui_modal] + modal[:props][:_inertiaui_modal] = @request.env[:_inertiaui_modal] + modal[:url] = modal[:props][:_inertiaui_modal][:url] + end + end + end +end) + +ActionController::Renderers.add :inertia_modal do |component, options| + InertiaRailsContrib::InertiaUIModalRenderer.new( + component, + self, + request, + response, + method(:render), + **options + ).render +end diff --git a/lib/inertia_rails_contrib/inertia_ui_modal_renderer.rb b/lib/inertia_rails_contrib/inertia_ui_modal_renderer.rb new file mode 100644 index 0000000..6ba595c --- /dev/null +++ b/lib/inertia_rails_contrib/inertia_ui_modal_renderer.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module InertiaRailsContrib + class InertiaUIModalRenderer + def initialize(component, controller, request, response, render_method, base_url: nil, **options) + @request = request + @response = response + @base_url = base_url + @inertia_renderer = InertiaRails::Renderer.new(component, controller, request, response, render_method, **options) + end + + def render + if @request.headers["X-InertiaUI-Modal-Use-Router"] == "0" || base_url.blank? + return @inertia_renderer.render + end + + @request.env[:_inertiaui_modal] = @inertia_renderer.page.merge(baseUrl: base_url) + + render_base_url + end + + def base_url + @request.headers["X-InertiaUI-Modal-Base-Url"] || @base_url + end + + def render_base_url + original_env = Rack::MockRequest.env_for( + base_url, + method: @request.method, + params: @request.params + ) + @request.each_header do |k, v| + original_env[k] ||= v + end + + original_request = ActionDispatch::Request.new(original_env) + + path = ActionDispatch::Journey::Router::Utils.normalize_path(original_request.path_info) + Rails.application.routes.recognize_path_with_request(original_request, path, {}) + controller = original_request.controller_class.new + controller.request = @request + controller.response = @response + controller.process(original_request.path_parameters[:action]) + end + end +end