Class: UltimateTurboModal::Base

Inherits:
Phlex::HTML
  • Object
show all
Includes:
Phlex::DeferredRenderWithMainContent
Defined in:
lib/ultimate_turbo_modal/base.rb

Constant Summary collapse

VALID_DRAWER_SIZES =
%i[xs sm md lg xl 2xl full].freeze
VALID_DRAWER_POSITIONS =
%i[right left].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(advance: nil, allowed_click_outside_selector: UltimateTurboModal.configuration.allowed_click_outside_selector, close_button: nil, close_button_data_action: "modal#hideModal", close_button_sr_label: "Close modal", drawer_position: false, footer_divider: nil, header: nil, header_divider: nil, overlay: nil, padding: nil, size: nil, content_div_data: nil, request: nil, title: nil) ⇒ Base

Returns a new instance of Base.

Parameters:

  • advance (Boolean, String) (defaults to: nil)

    Whether to update the browser history when opening and closing the modal (modal-only, ignored for drawers)

  • allowed_click_outside_selector (String) (defaults to: UltimateTurboModal.configuration.allowed_click_outside_selector)

    CSS selectors for elements that are allowed to be clicked outside of the modal without dismissing the modal

  • close_button (Boolean) (defaults to: nil)

    Whether to show a close button

  • close_button_data_action (String) (defaults to: "modal#hideModal")

    ‘data-action` attribute for the close button

  • close_button_sr_label (String) (defaults to: "Close modal")

    Close button label for screen readers

  • drawer_position (Symbol, false) (defaults to: false)

    Internal: drawer position (:right, :left) or false for standard modal. Use the ‘drawer()` view helper instead.

  • footer_divider (Boolean) (defaults to: nil)

    Whether to show a divider between the main content and the footer

  • header (Boolean) (defaults to: nil)

    Whether to show a modal header

  • header_divider (Boolean) (defaults to: nil)

    Whether to show a divider between the header and the main content

  • overlay (Boolean) (defaults to: nil)

    Whether to show a backdrop overlay

  • padding (Boolean) (defaults to: nil)

    Whether to add padding around the modal content

  • request (ActionDispatch::Request) (defaults to: nil)

    The current Rails request object

  • size (Symbol, String) (defaults to: nil)

    Drawer width preset (:xs, :sm, :md, :lg, :xl, :“2xl”, :full) or CSS string (drawer-only)

  • content_div_data (Hash) (defaults to: nil)

    ‘data` attribute for the div where the modal content will be rendered

  • title (String) (defaults to: nil)

    The title of the modal

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ultimate_turbo_modal/base.rb', line 25

def initialize(
  advance: nil,
  allowed_click_outside_selector: UltimateTurboModal.configuration.allowed_click_outside_selector,
  close_button: nil,
  close_button_data_action: "modal#hideModal",
  close_button_sr_label: "Close modal",
  drawer_position: false,
  footer_divider: nil,
  header: nil,
  header_divider: nil,
  overlay: nil,
  padding: nil,
  size: nil,
  content_div_data: nil,
  request: nil, title: nil
)
  @drawer = drawer_position
  @request = request

  raise ArgumentError, "Cannot render a drawer into the drawer-modal frame (drawers cannot be opened from inside another drawer or modal)" if drawer? && stacked?

  if drawer?
    cfg = UltimateTurboModal.configuration.drawer_config
    @advance = false
    @advance_url = nil
    @close_button = close_button.nil? ? cfg.close_button : close_button
    @drawer_size = self.class.validate_drawer_size!(size || cfg.size)
  else
    cfg = UltimateTurboModal.configuration.modal_config
    adv = advance.nil? ? cfg.advance : advance
    @advance = !!adv
    @advance_url = (adv.present? && adv.is_a?(String)) ? adv : nil
    @close_button = close_button.nil? ? cfg.close_button : close_button
    @drawer_size = nil
  end
  @footer_divider = footer_divider.nil? ? cfg.footer_divider : footer_divider
  @header = header.nil? ? cfg.header : header
  @header_divider = header_divider.nil? ? cfg.header_divider : header_divider
  @overlay = overlay.nil? ? cfg.overlay : overlay
  @padding = padding.nil? ? cfg.padding : padding

  if stacked?
    @advance = false
    @advance_url = nil
  end

  @allowed_click_outside_selector = allowed_click_outside_selector
  @close_button_data_action = close_button_data_action
  @close_button_sr_label = close_button_sr_label
  @content_div_data = content_div_data
  @title = title

  self.class.include_turbo_helpers
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, &block) ⇒ Object (private)



191
192
193
194
195
196
197
198
# File 'lib/ultimate_turbo_modal/base.rb', line 191

def method_missing(method, *, &block)
  mod = self.class.included_modules.find { |m| m.method_defined?(method) }
  if mod
    mod.instance_method(method).bind_call(self, *, &block)
  else
    super
  end
end

Instance Attribute Details

#allowed_click_outside_selectorObject

Returns the value of attribute allowed_click_outside_selector.



6
7
8
# File 'lib/ultimate_turbo_modal/base.rb', line 6

def allowed_click_outside_selector
  @allowed_click_outside_selector
end

#content_div_dataObject

Returns the value of attribute content_div_data.



6
7
8
# File 'lib/ultimate_turbo_modal/base.rb', line 6

def content_div_data
  @content_div_data
end

#requestObject

Returns the value of attribute request.



6
7
8
# File 'lib/ultimate_turbo_modal/base.rb', line 6

def request
  @request
end

Class Method Details

.include_turbo_helpersObject



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ultimate_turbo_modal/base.rb', line 80

def self.include_turbo_helpers
  return if @turbo_helpers_included

  include Turbo::FramesHelper
  include Turbo::StreamsHelper
  include Phlex::Rails::Helpers::ContentTag
  include Phlex::Rails::Helpers::Routes
  include Phlex::Rails::Helpers::Tag

  @turbo_helpers_included = true
end

.validate_drawer_position!(value) ⇒ Object

Raises:

  • (ArgumentError)


123
124
125
126
127
128
# File 'lib/ultimate_turbo_modal/base.rb', line 123

def validate_drawer_position!(value)
  return value if VALID_DRAWER_POSITIONS.include?(value.to_s.to_sym)

  raise ArgumentError,
    "Invalid drawer position: #{value.inspect}. Must be one of #{VALID_DRAWER_POSITIONS.map(&:inspect).join(", ")}"
end

.validate_drawer_size!(value) ⇒ Object

Raises:

  • (ArgumentError)


115
116
117
118
119
120
121
# File 'lib/ultimate_turbo_modal/base.rb', line 115

def validate_drawer_size!(value)
  return value if VALID_DRAWER_SIZES.include?(value.to_s.to_sym)
  return value if value.is_a?(String) && value.match?(/\A\d+(\.\d+)?\s*(rem|em|px|%|vw|vh|dvw|dvh|svw|svh|lvw|lvh|ch|ex|cm|mm|in|pt|pc)\z/)

  raise ArgumentError,
    "Invalid drawer size: #{value.inspect}. Must be one of #{VALID_DRAWER_SIZES.map(&:inspect).join(", ")} or a CSS length string (e.g., \"30rem\", \"500px\", \"50vw\")"
end

Instance Method Details



110
111
112
# File 'lib/ultimate_turbo_modal/base.rb', line 110

def footer(&block)
  @footer = block
end

#title(&block) ⇒ Object



106
107
108
# File 'lib/ultimate_turbo_modal/base.rb', line 106

def title(&block)
  @title_block = block
end

#turbo_frame_nameObject



102
103
104
# File 'lib/ultimate_turbo_modal/base.rb', line 102

def turbo_frame_name
  stacked? ? "drawer-modal" : "modal"
end

#view_template(&block) ⇒ Object



92
93
94
95
96
97
98
99
100
# File 'lib/ultimate_turbo_modal/base.rb', line 92

def view_template(&block)
  if turbo_frame?
    turbo_frame_tag(turbo_frame_name) do
      drawer? ? render_drawer(&block) : render_modal(&block)
    end
  else
    render block
  end
end