ultimate_turbo_modal 1.1.1 → 1.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +16 -1
- data/Gemfile.lock +1 -1
- data/README.md +61 -5
- data/lib/ultimate_turbo_modal/base.rb +52 -56
- data/lib/ultimate_turbo_modal/configuration.rb +68 -0
- data/lib/ultimate_turbo_modal/flavors/tailwind.rb +75 -49
- data/lib/ultimate_turbo_modal/flavors/vanilla.rb +73 -52
- data/lib/ultimate_turbo_modal/helpers/view_helper.rb +2 -4
- data/lib/ultimate_turbo_modal/version.rb +1 -1
- data/lib/ultimate_turbo_modal.rb +1 -10
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a456aa7e0fdb49a0b9ae53817f965df422145433f6d981811cbb0172126422dd
|
4
|
+
data.tar.gz: 4fdb91772d698e7d1987024acb165f1ef8380446d600c5146b834025cb84c497
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63ae9236655b7d2d300507413808a5771ca205dc12d08eecc48a3f256ddf24525f8b2b401a432a4df035d6fbd929c738e0a74c5bd1036a1f16b62b786ce756bb
|
7
|
+
data.tar.gz: d5fc098465cdba81f1981e49cce9721e049db78d02a448e734ea60f0c41b6119311a15e1ac922c7d0667d274431cb86bacaf9d3310c2ee51979f695cee3135ac
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
-
## [
|
1
|
+
## [1.2.0] - 2023-11-05
|
2
|
+
|
3
|
+
- Dark mode support
|
4
|
+
- Added header divider (configurable)
|
5
|
+
- Added footer section with divider (configurable)
|
6
|
+
- Tailwind flavor now uses data attributes to style elements
|
7
|
+
- Updated look and feel
|
8
|
+
- Simplified code a bit
|
9
|
+
|
10
|
+
## [1.1.3] - 2023-11-01
|
11
|
+
|
12
|
+
- Added configuration block
|
13
|
+
|
14
|
+
## [1.1.2] - 2023-10-31
|
15
|
+
|
16
|
+
- Bug fix
|
2
17
|
|
3
18
|
## [1.1.0] - 2023-10-31
|
4
19
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ UTMR aims to be the be-all and end-all of Turbo Modals. I believe it is the best
|
|
6
6
|
|
7
7
|
Under the hood, it uses [Stimulus](https://stimulus.hotwired.dev), [Turbo](https://turbo.hotwired.dev/), [el-transition](https://github.com/mmccall10/el-transition), and optionally [Idiomorph](https://github.com/bigskysoftware/idiomorph).
|
8
8
|
|
9
|
-
It currently ships in a two flavors: Tailwind CSS, and regular, vanilla CSS. It is easy to create your own to suit your needs
|
9
|
+
It currently ships in a two flavors: Tailwind CSS, and regular, vanilla CSS. It is easy to create your own variant to suit your needs. See `lib/ultimate_turbo_modal/flavors/vanilla.rb` for an example code.
|
10
10
|
|
11
11
|
|
12
12
|
|
@@ -34,7 +34,7 @@ It currently ships in a two flavors: Tailwind CSS, and regular, vanilla CSS. It
|
|
34
34
|
|
35
35
|
## Demo
|
36
36
|
|
37
|
-
A demo application can be found at https://github.com/cmer/ultimate_turbo_modal-demo. A video demo can be seen here: [https://youtu.be/
|
37
|
+
A demo application can be found at https://github.com/cmer/ultimate_turbo_modal-demo. A video demo can be seen here: [https://youtu.be/BVRDXLN1I78](https://youtu.be/BVRDXLN1I78).
|
38
38
|
|
39
39
|
|
40
40
|
|
@@ -59,10 +59,18 @@ A demo application can be found at https://github.com/cmer/ultimate_turbo_modal-
|
|
59
59
|
<%= turbo_frame_tag "modal" %>
|
60
60
|
``````
|
61
61
|
|
62
|
-
4. Set your desired flavor at `app/config/initializers/
|
62
|
+
4. Set your desired flavor and default configuration at `app/config/initializers/ultimate_turbo_modal.rb`.
|
63
63
|
|
64
64
|
```ruby
|
65
|
-
UltimateTurboModal.
|
65
|
+
UltimateTurboModal.configure do |config|
|
66
|
+
config.flavor = :tailwind
|
67
|
+
config.padding = true
|
68
|
+
config.advance = true
|
69
|
+
config.close_button = true
|
70
|
+
config.header = true
|
71
|
+
config.header_divider = true
|
72
|
+
config.footer_divider = true
|
73
|
+
end
|
66
74
|
```
|
67
75
|
|
68
76
|
5. Register the Stimulus controller in `app/javascript/controllers/index.js` adding the following lines at the end.
|
@@ -72,7 +80,33 @@ import setupUltimateTurboModal from "ultimate_turbo_modal";
|
|
72
80
|
setupUltimateTurboModal(application);
|
73
81
|
```
|
74
82
|
|
75
|
-
6.
|
83
|
+
6. If using the Tailwind flavor, add the following to `tailwind.config.js`:
|
84
|
+
|
85
|
+
```
|
86
|
+
// For npm/yarn
|
87
|
+
const { getUltimateTurboModalPath } = require('ultimate_turbo_modal/gemPath');
|
88
|
+
|
89
|
+
// If using Importmaps, use the following instead:
|
90
|
+
// const { execSync } = require('child_process');
|
91
|
+
//
|
92
|
+
// function getUltimateTurboModalPath() {
|
93
|
+
// const path = execSync('bundle show ultimate_turbo_modal').toString().trim();
|
94
|
+
// return `${path}/**/*.{erb,html,rb}`;
|
95
|
+
//}
|
96
|
+
```
|
97
|
+
|
98
|
+
and then in the `content` section, add `getUltimateTurboModalPath()` as follow:
|
99
|
+
|
100
|
+
```
|
101
|
+
content: [
|
102
|
+
'./public/*.html',
|
103
|
+
'./app/helpers/**/*.rb',
|
104
|
+
'./app/javascript/**/*.js',
|
105
|
+
'./app/views/**/*.{erb,haml,html,slim,rb}',
|
106
|
+
getUltimateTurboModalPath()
|
107
|
+
```
|
108
|
+
|
109
|
+
7. Optionally (but recommended), configure UTMR to use Idiomorph. See below for details.
|
76
110
|
|
77
111
|
|
78
112
|
|
@@ -122,6 +156,23 @@ When opening the modal, the URL in the URL bar will change to the URL of the vie
|
|
122
156
|
|
123
157
|
If a URL is specified as a String, the browser history will advance, and the URL shown in the URL bad will be replaced by the URL specified.
|
124
158
|
|
159
|
+
### `title`, default: `nil`
|
160
|
+
|
161
|
+
Title to display in the modal header.
|
162
|
+
|
163
|
+
### `header`, default: `true`
|
164
|
+
|
165
|
+
Whether to display a modal header.
|
166
|
+
|
167
|
+
### `header_divider`, default: `true`
|
168
|
+
|
169
|
+
Whether to display a divider below the header.
|
170
|
+
|
171
|
+
### `footer_divider`, default: `true`
|
172
|
+
|
173
|
+
Whether to display a divider above the footer. The divider will not appear if no footer was specified.
|
174
|
+
|
175
|
+
|
125
176
|
|
126
177
|
### Example usage with options
|
127
178
|
|
@@ -161,6 +212,11 @@ addEventListener("turbo:before-frame-render", (event) => {
|
|
161
212
|
})
|
162
213
|
```
|
163
214
|
|
215
|
+
|
216
|
+
|
217
|
+
## Thanks
|
218
|
+
|
219
|
+
Thanks to [@joeldrapper](https://github.com/KonnorRogers) and [@konnorrogers](https://github.com/KonnorRogers) for all the help!
|
164
220
|
|
165
221
|
|
166
222
|
|
@@ -1,90 +1,86 @@
|
|
1
1
|
class UltimateTurboModal::Base < Phlex::HTML
|
2
|
-
INCLUDES = %w[
|
3
|
-
Turbo::FramesHelper
|
4
|
-
Turbo::StreamsHelper
|
5
|
-
Phlex::Rails::Helpers::ContentTag
|
6
|
-
Phlex::Rails::Helpers::Routes
|
7
|
-
Phlex::Rails::Helpers::Tag
|
8
|
-
].freeze
|
9
|
-
|
10
2
|
# @param padding [Boolean] Whether to add padding around the modal content
|
11
3
|
# @param close_button [Boolean] Whether to show a close button.
|
12
4
|
# @param advance [Boolean] Whether to update the browser history when opening and closing the modal
|
13
|
-
# @param
|
5
|
+
# @param header_divider [Boolean] Whether to show a divider between the header and the main content
|
6
|
+
# @param footer_divider [Boolean] Whether to show a divider between the main content and the footer
|
7
|
+
# @param title [String] The title of the modal
|
14
8
|
# @param request [ActionDispatch::Request] The current Rails request object
|
15
|
-
def initialize(
|
9
|
+
def initialize(
|
10
|
+
padding: UltimateTurboModal.configuration.padding,
|
11
|
+
close_button: UltimateTurboModal.configuration.close_button,
|
12
|
+
advance: UltimateTurboModal.configuration.advance,
|
13
|
+
header: UltimateTurboModal.configuration.header,
|
14
|
+
header_divider: UltimateTurboModal.configuration.header_divider,
|
15
|
+
footer_divider: UltimateTurboModal.configuration.footer_divider,
|
16
|
+
title: nil, request: nil
|
17
|
+
)
|
16
18
|
@padding = padding
|
17
19
|
@close_button = close_button
|
18
|
-
@advance = advance
|
19
|
-
@advance_url = advance if advance && advance.is_a?(String)
|
20
|
+
@advance = !!advance
|
21
|
+
@advance_url = advance if advance.present? && advance.is_a?(String)
|
22
|
+
@title = title
|
23
|
+
@header = header
|
24
|
+
@header_divider = header_divider
|
25
|
+
@footer_divider = footer_divider
|
20
26
|
@request = request
|
21
27
|
|
22
|
-
self.class.include
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
unless self.class.include?(Turbo::FramesHelper)
|
29
|
+
self.class.include Turbo::FramesHelper
|
30
|
+
self.class.include Turbo::StreamsHelper
|
31
|
+
self.class.include Phlex::Rails::Helpers::ContentTag
|
32
|
+
self.class.include Phlex::Rails::Helpers::Routes
|
33
|
+
self.class.include Phlex::Rails::Helpers::Tag
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
|
-
def template(&)
|
37
|
+
def template(&block)
|
30
38
|
if turbo_frame?
|
31
|
-
turbo_frame_tag("modal")
|
39
|
+
turbo_frame_tag("modal") do
|
40
|
+
modal(&block)
|
41
|
+
end
|
32
42
|
elsif turbo_stream?
|
33
43
|
Turbo::StreamsHelper.turbo_stream_action_tag("update", target: "modal") do
|
34
|
-
|
44
|
+
modal(&block)
|
35
45
|
end
|
36
46
|
else
|
37
|
-
|
47
|
+
render block
|
38
48
|
end
|
39
49
|
end
|
40
50
|
|
51
|
+
def footer(&block)
|
52
|
+
@footer = block
|
53
|
+
end
|
54
|
+
|
41
55
|
private
|
42
56
|
|
43
|
-
attr_accessor :request
|
57
|
+
attr_accessor :request, :title
|
44
58
|
|
45
|
-
def padding?
|
46
|
-
!!@padding
|
47
|
-
end
|
59
|
+
def padding? = !!@padding
|
48
60
|
|
49
|
-
def
|
50
|
-
!!@advance
|
51
|
-
end
|
61
|
+
def close_button? = !!@close_button
|
52
62
|
|
53
|
-
def
|
54
|
-
!!@close_button
|
55
|
-
end
|
63
|
+
def title? = !!@title
|
56
64
|
|
57
|
-
def
|
58
|
-
!!request&.format&.turbo_stream?
|
59
|
-
end
|
65
|
+
def header? = !!@header
|
60
66
|
|
61
|
-
def
|
62
|
-
!!request&.headers&.key?("Turbo-Frame")
|
63
|
-
end
|
67
|
+
def footer? = @footer.present?
|
64
68
|
|
65
|
-
def
|
66
|
-
turbo_stream? || turbo_frame?
|
67
|
-
end
|
69
|
+
def header_divider? = !!@header_divider && title?
|
68
70
|
|
69
|
-
def
|
70
|
-
return nil unless advance?
|
71
|
-
@advance_url || request.original_url
|
72
|
-
end
|
71
|
+
def footer_divider? = !!@footer_divider && footer?
|
73
72
|
|
74
|
-
def
|
75
|
-
INCLUDES.each { |mod| include_if_defined(mod) }
|
73
|
+
def turbo_stream? = !!request&.format&.turbo_stream?
|
76
74
|
|
77
|
-
|
78
|
-
send(method, *, &block)
|
79
|
-
else
|
80
|
-
super
|
81
|
-
end
|
82
|
-
end
|
75
|
+
def turbo_frame? = !!request&.headers&.key?("Turbo-Frame")
|
83
76
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
77
|
+
def turbo? = turbo_stream? || turbo_frame?
|
78
|
+
|
79
|
+
def advance? = !!@advance && !!@advance_url
|
80
|
+
|
81
|
+
def advance_url
|
82
|
+
return nil unless !!@advance
|
83
|
+
@advance_url || request&.original_url
|
88
84
|
end
|
89
85
|
|
90
86
|
def respond_to_missing?(method, include_private = false)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module UltimateTurboModal
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield(configuration) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
delegate :flavor, :flavor=, :close_button, :close_button=,
|
12
|
+
:advance, :advance=, :padding, :padding=, to: :configuration
|
13
|
+
|
14
|
+
class Configuration
|
15
|
+
attr_reader :flavor, :close_button, :advance, :padding, :header, :header_divider, :footer_divider
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@flavor = :tailwind
|
19
|
+
@close_button = true
|
20
|
+
@advance = true
|
21
|
+
@padding = true
|
22
|
+
@header = true
|
23
|
+
@header_divider = true
|
24
|
+
@footer_divider = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def flavor=(flavor)
|
28
|
+
raise ArgumentError.new("Value must be a symbol.") unless flavor.is_a?(Symbol) || flavor.is_a?(String)
|
29
|
+
@flavor = flavor.to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
def close_button=(close_button)
|
33
|
+
raise ArgumentError.new("Value must be a boolean.") unless [true, false].include?(close_button)
|
34
|
+
@close_button = close_button
|
35
|
+
end
|
36
|
+
|
37
|
+
def advance=(advance)
|
38
|
+
raise ArgumentError.new("Value must be a boolean.") unless [true, false].include?(advance)
|
39
|
+
@advance = advance
|
40
|
+
end
|
41
|
+
|
42
|
+
def padding=(padding)
|
43
|
+
if [true, false].include?(padding) || padding.is_a?(String)
|
44
|
+
@padding = padding
|
45
|
+
else
|
46
|
+
raise ArgumentError.new("Value must be a boolean or a String.")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def header=(header)
|
51
|
+
raise ArgumentError.new("Value must be a boolean.") unless [true, false].include?(header)
|
52
|
+
@header = header
|
53
|
+
end
|
54
|
+
|
55
|
+
def header_divider=(header_divider)
|
56
|
+
raise ArgumentError.new("Value must be a boolean.") unless [true, false].include?(header_divider)
|
57
|
+
@header_divider = header_divider
|
58
|
+
end
|
59
|
+
|
60
|
+
def footer_divider=(footer_divider)
|
61
|
+
raise ArgumentError.new("Value must be a boolean.") unless [true, false].include?(footer_divider)
|
62
|
+
@footer_divider = footer_divider
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Make sure the configuration object is set up when the gem is loaded.
|
68
|
+
UltimateTurboModal.configure
|
@@ -1,27 +1,33 @@
|
|
1
1
|
module UltimateTurboModal::Flavors
|
2
2
|
class Tailwind < UltimateTurboModal::Base
|
3
|
+
|
3
4
|
private
|
4
5
|
|
5
6
|
def modal(&)
|
7
|
+
outer_divs do
|
8
|
+
div_content do
|
9
|
+
div_header
|
10
|
+
div_main(&)
|
11
|
+
div_footer if footer?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def outer_divs(&)
|
6
17
|
div_dialog do
|
7
18
|
div_overlay
|
8
19
|
div_outer do
|
9
|
-
div_inner
|
10
|
-
div_border do
|
11
|
-
button_close if close_button?
|
12
|
-
yield
|
13
|
-
end
|
14
|
-
end
|
20
|
+
div_inner(&)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
25
|
def div_dialog(&)
|
20
26
|
div(id: "modal-container",
|
21
|
-
class: "relative
|
27
|
+
class: "relative group",
|
22
28
|
role: "dialog",
|
23
29
|
aria: {
|
24
|
-
labeled_by: "modal-title",
|
30
|
+
labeled_by: "modal-title-h",
|
25
31
|
modal: true
|
26
32
|
},
|
27
33
|
data: {
|
@@ -29,71 +35,91 @@ module UltimateTurboModal::Flavors
|
|
29
35
|
modal_target: "container",
|
30
36
|
modal_advance_url_value: advance_url,
|
31
37
|
action: "turbo:submit-end->modal#submitEnd keyup@window->modal#closeWithKeyboard click@window->modal#outsideModalClicked click->modal#outsideModalClicked",
|
32
|
-
transition_enter: "ease-out duration-
|
38
|
+
transition_enter: "ease-out duration-100",
|
33
39
|
transition_enter_start: "opacity-0",
|
34
40
|
transition_enter_end: "opacity-100",
|
35
|
-
transition_leave: "ease-in duration-
|
41
|
+
transition_leave: "ease-in duration-50",
|
36
42
|
transition_leave_start: "opacity-100",
|
37
|
-
transition_leave_end: "opacity-0"
|
43
|
+
transition_leave_end: "opacity-0",
|
44
|
+
padding: padding?.to_s,
|
45
|
+
title: title?.to_s,
|
46
|
+
header: header?.to_s,
|
47
|
+
close_button: close_button?.to_s,
|
48
|
+
header_divider: header_divider?.to_s,
|
49
|
+
footer_divider: footer_divider?.to_s
|
38
50
|
}, &)
|
39
51
|
end
|
40
52
|
|
41
|
-
def div_overlay
|
53
|
+
def div_overlay
|
42
54
|
div(id: "modal-overlay",
|
43
|
-
class: "fixed inset-0 bg-gray-
|
44
|
-
data: {
|
45
|
-
modal_target: "overlay",
|
46
|
-
action: "click->modal#outsideModalClicked"
|
47
|
-
})
|
55
|
+
class: "fixed inset-0 bg-gray-900 bg-opacity-50 transition-opacity dark:bg-opacity-80 z-40")
|
48
56
|
end
|
49
57
|
|
50
58
|
def div_outer(&)
|
51
59
|
div(id: "modal-outer",
|
52
|
-
class: "fixed inset-0 z-
|
53
|
-
data: {
|
54
|
-
modal_target: "modal"
|
55
|
-
}, &)
|
60
|
+
class: "fixed inset-0 z-50 overflow-y-auto sm:max-w-[80%] md:max-w-3xl sm:mx-auto m-4", &)
|
56
61
|
end
|
57
62
|
|
58
63
|
def div_inner(&)
|
59
64
|
div(id: "modal-inner",
|
60
|
-
class: "flex min-h-full items-center justify-center p-1 sm:p-4",
|
61
|
-
|
62
|
-
|
63
|
-
|
65
|
+
class: "flex min-h-full items-center justify-center p-1 sm:p-4", &)
|
66
|
+
end
|
67
|
+
|
68
|
+
def div_content(&)
|
69
|
+
div(id: "modal-content",
|
70
|
+
class: "relative transform overflow-hidden rounded-lg bg-white text-left shadow transition-all
|
71
|
+
sm:my-8 sm:max-w-3xl dark:bg-gray-800 dark:text-white",
|
72
|
+
data: {modal_target: "content"}, &)
|
73
|
+
end
|
74
|
+
|
75
|
+
def div_main(&)
|
76
|
+
div(id: "modal-main", class: "group-data-[padding=true]:p-4 group-data-[padding=true]:pt-2", &)
|
64
77
|
end
|
65
78
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
def div_header(&)
|
80
|
+
div(id: "modal-header", class: "flex justify-between items-center w-full py-4 rounded-t dark:border-gray-600 group-data-[header-divider=true]:border-b group-data-[header=false]:absolute") do
|
81
|
+
div_title
|
82
|
+
button_close
|
83
|
+
end
|
71
84
|
end
|
72
85
|
|
73
|
-
def
|
74
|
-
div(
|
75
|
-
|
76
|
-
aria: {label: "close"},
|
77
|
-
class: "ml-auto inline-flex items-center rounded bg-transparent p-1 text-sm text-gray-400 bg-white bg-opacity-20 hover:bg-gray-100 hover:bg-opacity-70 hover:text-gray-900",
|
78
|
-
data: {
|
79
|
-
action: "modal#hideModal"
|
80
|
-
}) { icon_close }
|
86
|
+
def div_title
|
87
|
+
div(id: "modal-title", class: "pl-4") do
|
88
|
+
h3(id: "modal-title-h", class: "group-data-[title=false]:hidden text-lg font-semibold text-gray-900 dark:text-white") { @title }
|
81
89
|
end
|
82
90
|
end
|
83
91
|
|
92
|
+
def div_footer
|
93
|
+
div(id: "modal-footer", class: "flex p-4 rounded-b dark:border-gray-600 group-data-[footer-divider=true]:border-t") do
|
94
|
+
render @footer
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def button_close
|
99
|
+
div(id: "modal-close", class: "mr-4") do
|
100
|
+
close_button_tag do
|
101
|
+
icon_close
|
102
|
+
span(class: "sr-only") { "Close modal" }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def close_button_tag(&)
|
108
|
+
button(type: "button",
|
109
|
+
aria: {label: "close"},
|
110
|
+
class: "text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm
|
111
|
+
p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white",
|
112
|
+
data: {
|
113
|
+
action: "modal#hideModal"
|
114
|
+
}, &)
|
115
|
+
end
|
116
|
+
|
84
117
|
def icon_close
|
85
|
-
svg(
|
86
|
-
xmlns: "http://www.w3.org/2000/svg",
|
87
|
-
fill: "none",
|
88
|
-
viewbox: "0 0 24 24",
|
89
|
-
stroke_width: "1.5",
|
90
|
-
stroke: "currentColor",
|
91
|
-
class: "w-5 h-5"
|
92
|
-
) do |s|
|
118
|
+
svg(class: "w-5 h-5", fill: "currentColor", viewBox: "0 0 20 20") do |s|
|
93
119
|
s.path(
|
94
|
-
|
95
|
-
|
96
|
-
|
120
|
+
fill_rule: "evenodd",
|
121
|
+
d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
|
122
|
+
clip_rule: "evenodd"
|
97
123
|
)
|
98
124
|
end
|
99
125
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
module UltimateTurboModal::Flavors
|
2
2
|
class Vanilla < UltimateTurboModal::Base
|
3
|
+
|
3
4
|
private
|
4
5
|
|
5
6
|
def modal(&)
|
7
|
+
outer_divs do
|
8
|
+
div_content do
|
9
|
+
div_header
|
10
|
+
div_main(&)
|
11
|
+
div_footer if footer?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def outer_divs(&)
|
6
17
|
div_dialog do
|
7
18
|
div_overlay
|
8
|
-
|
9
|
-
|
10
|
-
div_border do
|
11
|
-
button_close if close_button?
|
12
|
-
yield
|
13
|
-
end
|
14
|
-
end
|
19
|
+
div_outer do
|
20
|
+
div_inner(&)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -21,7 +27,7 @@ module UltimateTurboModal::Flavors
|
|
21
27
|
class: "modal-container",
|
22
28
|
role: "dialog",
|
23
29
|
aria: {
|
24
|
-
labeled_by: "modal-title",
|
30
|
+
labeled_by: "modal-title-h",
|
25
31
|
modal: true
|
26
32
|
},
|
27
33
|
data: {
|
@@ -29,69 +35,84 @@ module UltimateTurboModal::Flavors
|
|
29
35
|
modal_target: "container",
|
30
36
|
modal_advance_url_value: advance_url,
|
31
37
|
action: "turbo:submit-end->modal#submitEnd keyup@window->modal#closeWithKeyboard click@window->modal#outsideModalClicked click->modal#outsideModalClicked",
|
32
|
-
transition_enter: "ease-out duration-
|
38
|
+
transition_enter: "ease-out duration-100",
|
33
39
|
transition_enter_start: "opacity-0",
|
34
40
|
transition_enter_end: "opacity-100",
|
35
|
-
transition_leave: "ease-in duration-
|
41
|
+
transition_leave: "ease-in duration-50",
|
36
42
|
transition_leave_start: "opacity-100",
|
37
|
-
transition_leave_end: "opacity-0"
|
43
|
+
transition_leave_end: "opacity-0",
|
44
|
+
padding: padding?.to_s,
|
45
|
+
title: title?.to_s,
|
46
|
+
header: header?.to_s,
|
47
|
+
close_button: close_button?.to_s,
|
48
|
+
header_divider: header_divider?.to_s,
|
49
|
+
footer_divider: footer_divider?.to_s
|
38
50
|
}, &)
|
39
51
|
end
|
40
52
|
|
41
|
-
def div_overlay
|
42
|
-
div(id: "modal-overlay",
|
43
|
-
class: "modal-overlay",
|
44
|
-
data: {
|
45
|
-
modal_target: "overlay",
|
46
|
-
action: "click->modal#outsideModalClicked"
|
47
|
-
})
|
53
|
+
def div_overlay
|
54
|
+
div(id: "modal-overlay", class: "modal-overlay")
|
48
55
|
end
|
49
56
|
|
50
|
-
def
|
51
|
-
div(id: "modal-outer",
|
52
|
-
class: "modal-outer",
|
53
|
-
data: {
|
54
|
-
modal_target: "modal"
|
55
|
-
}, &)
|
57
|
+
def div_outer(&)
|
58
|
+
div(id: "modal-outer", class: "modal-outer", &)
|
56
59
|
end
|
57
60
|
|
58
|
-
def
|
59
|
-
div(id: "modal-inner",
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
def div_inner(&)
|
62
|
+
div(id: "modal-inner", class: "modal-inner", &)
|
63
|
+
end
|
64
|
+
|
65
|
+
def div_content(&)
|
66
|
+
div(id: "modal-content", class: "modal-content", data: {modal_target: "content"}, &)
|
67
|
+
end
|
68
|
+
|
69
|
+
def div_main(&)
|
70
|
+
div(id: "modal-main", class: "modal-main", &)
|
64
71
|
end
|
65
72
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
def div_header(&)
|
74
|
+
div(id: "modal-header", class: "modal-header") do
|
75
|
+
div_title
|
76
|
+
button_close
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
|
-
def
|
74
|
-
div(class: "modal-
|
75
|
-
|
76
|
-
aria: {label: "close"},
|
77
|
-
data: {
|
78
|
-
action: "modal#hideModal"
|
79
|
-
}) { icon_close }
|
80
|
+
def div_title
|
81
|
+
div(id: "modal-title", class: "modal-title") do
|
82
|
+
h3(id: "modal-title-h", class: "modal-title-h") { @title }
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
86
|
+
def div_footer
|
87
|
+
div(id: "modal-footer", class: "modal-footer") do
|
88
|
+
render @footer
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def button_close
|
93
|
+
div(id: "modal-close", class: "modal-close") do
|
94
|
+
close_button_tag do
|
95
|
+
icon_close
|
96
|
+
span(class: "sr-only") { "Close modal" }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def close_button_tag(&)
|
102
|
+
button(type: "button",
|
103
|
+
aria: {label: "close"},
|
104
|
+
class: "modal-close-button",
|
105
|
+
data: {
|
106
|
+
action: "modal#hideModal"
|
107
|
+
}, &)
|
108
|
+
end
|
109
|
+
|
83
110
|
def icon_close
|
84
|
-
svg(
|
85
|
-
xmlns: "http://www.w3.org/2000/svg",
|
86
|
-
fill: "none",
|
87
|
-
viewbox: "0 0 24 24",
|
88
|
-
stroke_width: "1.5",
|
89
|
-
stroke: "currentColor",
|
90
|
-
) do |s|
|
111
|
+
svg(class: "modal-close-icon", fill: "currentColor", viewBox: "0 0 20 20") do |s|
|
91
112
|
s.path(
|
92
|
-
|
93
|
-
|
94
|
-
|
113
|
+
fill_rule: "evenodd",
|
114
|
+
d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
|
115
|
+
clip_rule: "evenodd"
|
95
116
|
)
|
96
117
|
end
|
97
118
|
end
|
data/lib/ultimate_turbo_modal.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "ultimate_turbo_modal/version"
|
4
|
+
require "ultimate_turbo_modal/configuration"
|
4
5
|
require "ultimate_turbo_modal/railtie"
|
5
6
|
require "ultimate_turbo_modal/base"
|
6
7
|
Dir[File.join(__dir__, "ultimate_turbo_modal/flavors", "*.rb")].sort.each do |file|
|
@@ -10,8 +11,6 @@ end
|
|
10
11
|
module UltimateTurboModal
|
11
12
|
extend self
|
12
13
|
|
13
|
-
DEFAULT_FLAVOR = :tailwind
|
14
|
-
|
15
14
|
def new(**)
|
16
15
|
modal_class.new(**)
|
17
16
|
end
|
@@ -20,13 +19,5 @@ module UltimateTurboModal
|
|
20
19
|
"UltimateTurboModal::Flavors::#{flavor.to_s.classify}".constantize
|
21
20
|
end
|
22
21
|
|
23
|
-
def flavor=(flavor)
|
24
|
-
@flavor = flavor
|
25
|
-
end
|
26
|
-
|
27
|
-
def flavor
|
28
|
-
defined?(@flavor) ? @flavor&.to_sym : DEFAULT_FLAVOR
|
29
|
-
end
|
30
|
-
|
31
22
|
class Error < StandardError; end
|
32
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ultimate_turbo_modal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carl Mercier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: phlex-rails
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- Rakefile
|
93
93
|
- lib/ultimate_turbo_modal.rb
|
94
94
|
- lib/ultimate_turbo_modal/base.rb
|
95
|
+
- lib/ultimate_turbo_modal/configuration.rb
|
95
96
|
- lib/ultimate_turbo_modal/flavors/tailwind.rb
|
96
97
|
- lib/ultimate_turbo_modal/flavors/vanilla.rb
|
97
98
|
- lib/ultimate_turbo_modal/helpers/controller_helper.rb
|