jet_ui 0.2.11 → 0.3.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/CHANGELOG.md +15 -0
- data/README.md +29 -20
- data/app/assets/javascripts/jet_ui/dialog_controller.js +95 -0
- data/app/assets/javascripts/jet_ui/dialogs_controller.js +248 -0
- data/app/assets/javascripts/jet_ui/drawer_controller.js +6 -0
- data/app/assets/javascripts/jet_ui/drawers_controller.js +5 -0
- data/app/assets/javascripts/jet_ui/modal_controller.js +6 -0
- data/app/assets/javascripts/jet_ui/modals_controller.js +5 -0
- data/app/assets/stylesheets/jet_ui/dialog.css +134 -0
- data/app/assets/stylesheets/jet_ui/theme.css +12 -0
- data/app/assets/stylesheets/jet_ui.css +1 -0
- data/app/components/jet_ui/dialog/body_component.rb +21 -0
- data/app/components/jet_ui/dialog/component.rb +86 -0
- data/app/components/jet_ui/dialog/footer_component.rb +45 -0
- data/app/components/jet_ui/dialog/header_component.rb +45 -0
- data/app/components/jet_ui/dialogs/component.rb +18 -0
- data/app/components/jet_ui/drawer/body_component.rb +2 -14
- data/app/components/jet_ui/drawer/component.rb +14 -44
- data/app/components/jet_ui/drawer/footer_component.rb +2 -38
- data/app/components/jet_ui/drawer/header_component.rb +6 -38
- data/app/components/jet_ui/modal/body_component.rb +2 -14
- data/app/components/jet_ui/modal/component.rb +14 -44
- data/app/components/jet_ui/modal/footer_component.rb +2 -38
- data/app/components/jet_ui/modal/header_component.rb +6 -38
- data/app/components/jet_ui/turbo_confirm/component.html.erb +13 -15
- data/lib/generators/jet_ui/eject/eject_generator.rb +19 -0
- data/lib/generators/jet_ui/install/install_generator.rb +3 -3
- data/lib/jet_ui/version.rb +1 -1
- metadata +10 -2
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
from { opacity: 0.8; transform: translateX(3rem); }
|
|
14
14
|
to { opacity: 1; transform: translateX(0); }
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
@keyframes slideRight {
|
|
18
|
+
from { opacity: 0.8; transform: translateX(-3rem); }
|
|
19
|
+
to { opacity: 1; transform: translateX(0); }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@keyframes slideDown {
|
|
23
|
+
from { opacity: 0.7; transform: translateY(-2rem); }
|
|
24
|
+
to { opacity: 1; transform: translateY(0); }
|
|
25
|
+
}
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
:root {
|
|
@@ -33,6 +43,8 @@
|
|
|
33
43
|
--animate-fade-in: fadeIn 0.15s ease-in-out;
|
|
34
44
|
--animate-slide-up: slideUp 0.3s ease-in-out;
|
|
35
45
|
--animate-slide-left: slideLeft 0.3s ease-in-out;
|
|
46
|
+
--animate-slide-right: slideRight 0.3s ease-in-out;
|
|
47
|
+
--animate-slide-down: slideDown 0.3s ease-in-out;
|
|
36
48
|
|
|
37
49
|
/* Radius */
|
|
38
50
|
--radius-btn-xs: calc(var(--radius-md) * 0.75);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JetUi
|
|
4
|
+
module Dialog
|
|
5
|
+
class BodyComponent < JetUi::BaseComponent
|
|
6
|
+
def initialize(**options)
|
|
7
|
+
@options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
content_tag :div, content, class: classes, **@options.except(:class)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def classes
|
|
17
|
+
class_names('dialog__body', @options[:class])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JetUi
|
|
4
|
+
module Dialog
|
|
5
|
+
class Component < JetUi::BaseComponent
|
|
6
|
+
SIZES = %w[sm md lg xl 2xl 3xl 4xl 5xl 6xl].freeze
|
|
7
|
+
DEFAULT_SIZE = '2xl'
|
|
8
|
+
|
|
9
|
+
POSITIONS = %i[center left right top bottom].freeze
|
|
10
|
+
DEFAULT_POSITION = :center
|
|
11
|
+
|
|
12
|
+
EDGE_POSITIONS = %i[left right top bottom].freeze
|
|
13
|
+
|
|
14
|
+
def initialize(title: nil, subtitle: nil, position: DEFAULT_POSITION, size: DEFAULT_SIZE,
|
|
15
|
+
id: nil, closable: true, dismissible: true, swipe: true)
|
|
16
|
+
@title = title
|
|
17
|
+
@subtitle = subtitle
|
|
18
|
+
@position = position.to_sym
|
|
19
|
+
@size = size.to_s
|
|
20
|
+
@id = id
|
|
21
|
+
@closable = closable
|
|
22
|
+
@dismissible = dismissible
|
|
23
|
+
@swipe = swipe && edge_position?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
erb_template <<~ERB
|
|
27
|
+
<%= container_tag do %>
|
|
28
|
+
<div class="dialog__panel" data-dialog-target="panel">
|
|
29
|
+
<%= helpers.jet_ui.dialog_header(title: @title, subtitle: @subtitle, closable: closable?) %>
|
|
30
|
+
<%= content %>
|
|
31
|
+
<div class="dialog__flash-slot"></div>
|
|
32
|
+
</div>
|
|
33
|
+
<% end %>
|
|
34
|
+
ERB
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def edge_position?
|
|
39
|
+
EDGE_POSITIONS.include?(@position)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def container_tag(&block)
|
|
43
|
+
# If @id is provided, we assume it's a sync dialog defined inline on the page.
|
|
44
|
+
return dialog_tag(id: @id, data: { dialogs_target: 'dialog' }, &block) if @id
|
|
45
|
+
|
|
46
|
+
# Async open (e.g. opened via a link with data: { turbo_frame: :dialog }).
|
|
47
|
+
# The <dialog> shell around this frame is created client-side by DialogsController
|
|
48
|
+
# before Turbo navigates the frame — see app/assets/javascripts/jet_ui/dialogs_controller.js.
|
|
49
|
+
return helpers.turbo_frame_tag(:dialog, &block) if helpers.turbo_frame_request?
|
|
50
|
+
|
|
51
|
+
# Not a Turbo Frame request (direct visit, new tab) — render as a plain page section.
|
|
52
|
+
content_tag :div, class: class_names('dialog-page', size_class), &block
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def dialog_tag(**options, &block)
|
|
56
|
+
content_tag :dialog, tabindex: '-1', class: dialog_classes, data: dialog_data(options.delete(:data)),
|
|
57
|
+
**options, &block
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def dialog_classes
|
|
61
|
+
class_names('dialog', "dialog-#{@position}", size_class)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def dialog_data(extra)
|
|
65
|
+
{
|
|
66
|
+
controller: 'dialog',
|
|
67
|
+
dialog_position_value: @position,
|
|
68
|
+
dialog_dismissible_value: @dismissible,
|
|
69
|
+
dialog_swipe_value: @swipe
|
|
70
|
+
}.merge(extra || {})
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def size_class
|
|
74
|
+
horizontal_edge? ? "h-#{@size}" : "w-#{@size}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def horizontal_edge?
|
|
78
|
+
%i[top bottom].include?(@position)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def closable?
|
|
82
|
+
@closable && (helpers.turbo_frame_request? || @id)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JetUi
|
|
4
|
+
module Dialog
|
|
5
|
+
class FooterComponent < JetUi::BaseComponent
|
|
6
|
+
def initialize(direction: :row, align: :start, justify: :start, bordered: true, **options)
|
|
7
|
+
@direction = direction
|
|
8
|
+
@align = align
|
|
9
|
+
@justify = justify
|
|
10
|
+
@bordered = bordered
|
|
11
|
+
@options = options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
content_tag :div, content, class: classes, **@options.except(:class)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def classes
|
|
21
|
+
class_names(
|
|
22
|
+
'dialog__footer',
|
|
23
|
+
{ 'dialog__footer-bordered' => @bordered },
|
|
24
|
+
direction_class,
|
|
25
|
+
align_class,
|
|
26
|
+
justify_class,
|
|
27
|
+
@options[:class]
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def direction_class
|
|
32
|
+
{ col: 'flex flex-col gap-2', row: 'flex flex-row gap-2' }[@direction]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def align_class
|
|
36
|
+
{ start: 'items-start', center: 'items-center', end: 'items-end' }[@align]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def justify_class
|
|
40
|
+
{ start: 'justify-start', center: 'justify-center', end: 'justify-end',
|
|
41
|
+
between: 'justify-between' }[@justify]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JetUi
|
|
4
|
+
module Dialog
|
|
5
|
+
class HeaderComponent < JetUi::BaseComponent
|
|
6
|
+
def initialize(title: nil, subtitle: nil, closable: true, bordered: true, **options)
|
|
7
|
+
@title = title
|
|
8
|
+
@subtitle = subtitle
|
|
9
|
+
@closable = closable
|
|
10
|
+
@bordered = bordered
|
|
11
|
+
@options = options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
erb_template <<~ERB
|
|
15
|
+
<div class="<%= classes %>">
|
|
16
|
+
<div>
|
|
17
|
+
<% if @title %>
|
|
18
|
+
<h3 class="dialog__title"><%= @title %></h3>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% if @subtitle %>
|
|
21
|
+
<div class="dialog__subtitle"><%= @subtitle %></div>
|
|
22
|
+
<% end %>
|
|
23
|
+
<%= content %>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<% if @closable %>
|
|
27
|
+
<button type="button" class="dialog__close" data-action="click->dialog#close" aria-label="Close">
|
|
28
|
+
<%= helpers.jet_ui.icon('x-mark', size: 6) %>
|
|
29
|
+
</button>
|
|
30
|
+
<% end %>
|
|
31
|
+
</div>
|
|
32
|
+
ERB
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def classes
|
|
37
|
+
class_names(
|
|
38
|
+
'dialog__header',
|
|
39
|
+
{ 'dialog__header-bordered' => @bordered },
|
|
40
|
+
@options[:class]
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JetUi
|
|
4
|
+
module Dialogs
|
|
5
|
+
# Mount point for the dialog stack. Renders the `#dialogs` root that DialogsController
|
|
6
|
+
# manages (see app/assets/javascripts/jet_ui/dialogs_controller.js) plus the sentinel
|
|
7
|
+
# <turbo-frame id="dialog"> that every async dialog open (data: { turbo_frame: :dialog })
|
|
8
|
+
# adopts into a freshly built <dialog> shell before Turbo navigates it. Render this once
|
|
9
|
+
# in the host application's layout.
|
|
10
|
+
class Component < JetUi::BaseComponent
|
|
11
|
+
erb_template <<~ERB
|
|
12
|
+
<div id="dialogs" data-dialogs-target="root" data-turbo-permanent data-turbo-cache="false">
|
|
13
|
+
<%= helpers.turbo_frame_tag :dialog, data: { dialogs_target: 'sentinel' } %>
|
|
14
|
+
</div>
|
|
15
|
+
ERB
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -2,20 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Drawer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@options = options
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def call
|
|
11
|
-
content_tag :div, content, class: classes, **@options.except(:class)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
def classes
|
|
17
|
-
class_names('drawer__body', @options[:class])
|
|
18
|
-
end
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::BodyComponent} instead.
|
|
6
|
+
class BodyComponent < JetUi::Dialog::BodyComponent
|
|
19
7
|
end
|
|
20
8
|
end
|
|
21
9
|
end
|
|
@@ -2,52 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Drawer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@
|
|
12
|
-
@size = size
|
|
13
|
-
@id = id
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
erb_template <<~ERB
|
|
17
|
-
<%= container_tag do %>
|
|
18
|
-
<%= helpers.jet_ui.drawer_header(title: @title, subtitle: @subtitle, closable: closable?, id: @id) %>
|
|
19
|
-
<%= content %>
|
|
20
|
-
<% end %>
|
|
21
|
-
ERB
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def container_tag(&block)
|
|
26
|
-
return sync_dialog(&block) if @id
|
|
27
|
-
return turbo_frame_dialog(&block) if helpers.turbo_frame_request?
|
|
28
|
-
|
|
29
|
-
content_tag :div, class: class_names('mx-auto bg-background', "w-#{@size}"), &block
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def sync_dialog(&block)
|
|
33
|
-
dialog_tag(id: @id, data: { drawers_target: 'dialog' }, &block)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def turbo_frame_dialog(&block)
|
|
37
|
-
helpers.turbo_frame_tag :drawer do
|
|
38
|
-
dialog_tag(id: :drawerDialog, data: { controller: 'drawer' }) do
|
|
39
|
-
helpers.turbo_frame_tag(:drawerContent, &block)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def dialog_tag(**options, &block)
|
|
45
|
-
attrs = { tabindex: '-1', class: class_names('drawer', 'animate-slide-left', "w-#{@size}") }
|
|
46
|
-
content_tag :dialog, **attrs, **options, &block
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::Component} with `position: :right` instead.
|
|
6
|
+
# Kept as a thin shim so existing `jet_ui.drawer(...)` calls and
|
|
7
|
+
# `data: { turbo_frame: :drawer }` links keep working. Will be removed in the next
|
|
8
|
+
# major version.
|
|
9
|
+
class Component < JetUi::Dialog::Component
|
|
10
|
+
def self.deprecator
|
|
11
|
+
@deprecator ||= ActiveSupport::Deprecation.new('1.0', 'JetUi')
|
|
47
12
|
end
|
|
48
13
|
|
|
49
|
-
def
|
|
50
|
-
|
|
14
|
+
def initialize(title: nil, subtitle: nil, size: JetUi::Dialog::Component::DEFAULT_SIZE, id: nil)
|
|
15
|
+
self.class.deprecator.warn(
|
|
16
|
+
'JetUi::Drawer::Component is deprecated and will be removed in the next major ' \
|
|
17
|
+
'version. Use JetUi::Dialog::Component with position: :right instead ' \
|
|
18
|
+
'(jet_ui.dialog).'
|
|
19
|
+
)
|
|
20
|
+
super(title: title, subtitle: subtitle, position: :right, size: size, id: id)
|
|
51
21
|
end
|
|
52
22
|
end
|
|
53
23
|
end
|
|
@@ -2,44 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Drawer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@direction = direction
|
|
8
|
-
@align = align
|
|
9
|
-
@justify = justify
|
|
10
|
-
@bordered = bordered
|
|
11
|
-
@options = options
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call
|
|
15
|
-
content_tag :div, content, class: classes, **@options.except(:class)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def classes
|
|
21
|
-
class_names(
|
|
22
|
-
'drawer__footer',
|
|
23
|
-
{ 'drawer__footer-bordered' => @bordered },
|
|
24
|
-
direction_class,
|
|
25
|
-
align_class,
|
|
26
|
-
justify_class,
|
|
27
|
-
@options[:class]
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def direction_class
|
|
32
|
-
{ col: 'flex flex-col gap-2', row: 'flex flex-row gap-2' }[@direction]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def align_class
|
|
36
|
-
{ start: 'items-start', center: 'items-center', end: 'items-end' }[@align]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def justify_class
|
|
40
|
-
{ start: 'justify-start', center: 'justify-center', end: 'justify-end',
|
|
41
|
-
between: 'justify-between' }[@justify]
|
|
42
|
-
end
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::FooterComponent} instead.
|
|
6
|
+
class FooterComponent < JetUi::Dialog::FooterComponent
|
|
43
7
|
end
|
|
44
8
|
end
|
|
45
9
|
end
|
|
@@ -2,44 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Drawer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@bordered = bordered
|
|
12
|
-
@options = options
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
erb_template <<~ERB
|
|
16
|
-
<div class="<%= classes %>">
|
|
17
|
-
<div>
|
|
18
|
-
<% if @title %>
|
|
19
|
-
<h3 class="drawer__title"><%= @title %></h3>
|
|
20
|
-
<% end %>
|
|
21
|
-
<% if @subtitle %>
|
|
22
|
-
<div class="drawer__subtitle"><%= @subtitle %></div>
|
|
23
|
-
<% end %>
|
|
24
|
-
<%= content %>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<% if @closable %>
|
|
28
|
-
<button type="button" class="drawer__close" data-action="click->drawer#close click->drawers#close" aria-label="Close" data-id="<%= @id %>">
|
|
29
|
-
<%= helpers.jet_ui.icon("x-mark", size: 6) %>
|
|
30
|
-
</button>
|
|
31
|
-
<% end %>
|
|
32
|
-
</div>
|
|
33
|
-
ERB
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def classes
|
|
38
|
-
class_names(
|
|
39
|
-
'drawer__header',
|
|
40
|
-
{ 'drawer__header-bordered' => @bordered },
|
|
41
|
-
@options[:class]
|
|
42
|
-
)
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::HeaderComponent} instead.
|
|
6
|
+
class HeaderComponent < JetUi::Dialog::HeaderComponent
|
|
7
|
+
# `id:` accepted and ignored for signature compatibility with the pre-deprecation API.
|
|
8
|
+
def initialize(title: nil, subtitle: nil, closable: true, id: nil, bordered: true, # rubocop:disable Lint/UnusedMethodArgument
|
|
9
|
+
**options)
|
|
10
|
+
super(title: title, subtitle: subtitle, closable: closable, bordered: bordered, **options)
|
|
43
11
|
end
|
|
44
12
|
end
|
|
45
13
|
end
|
|
@@ -2,20 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Modal
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@options = options
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def call
|
|
11
|
-
content_tag :div, content, class: classes, **@options.except(:class)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
def classes
|
|
17
|
-
class_names('modal__body', @options[:class])
|
|
18
|
-
end
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::BodyComponent} instead.
|
|
6
|
+
class BodyComponent < JetUi::Dialog::BodyComponent
|
|
19
7
|
end
|
|
20
8
|
end
|
|
21
9
|
end
|
|
@@ -2,52 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Modal
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@
|
|
12
|
-
@size = size
|
|
13
|
-
@id = id
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
erb_template <<~ERB
|
|
17
|
-
<%= container_tag do %>
|
|
18
|
-
<%= helpers.jet_ui.modal_header(title: @title, subtitle: @subtitle, closable: closable?, id: @id) %>
|
|
19
|
-
<%= content %>
|
|
20
|
-
<% end %>
|
|
21
|
-
ERB
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def container_tag(&block)
|
|
26
|
-
return sync_dialog(&block) if @id
|
|
27
|
-
return turbo_frame_dialog(&block) if helpers.turbo_frame_request?
|
|
28
|
-
|
|
29
|
-
content_tag :div, class: class_names('modal modal-page', "w-#{@size}"), &block
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def sync_dialog(&block)
|
|
33
|
-
dialog_tag(id: @id, data: { modals_target: 'dialog' }, &block)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def turbo_frame_dialog(&block)
|
|
37
|
-
helpers.turbo_frame_tag :modal do
|
|
38
|
-
dialog_tag(id: :modalDialog, data: { controller: 'modal' }) do
|
|
39
|
-
helpers.turbo_frame_tag(:modalContent, &block)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def dialog_tag(**options, &block)
|
|
45
|
-
attrs = { tabindex: '-1', class: class_names('modal', 'animate-slide-up', "w-#{@size}") }
|
|
46
|
-
content_tag :dialog, **attrs, **options, &block
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::Component} with `position: :center` instead.
|
|
6
|
+
# Kept as a thin shim so existing `jet_ui.modal(...)` calls and
|
|
7
|
+
# `data: { turbo_frame: :modal }` links keep working. Will be removed in the next
|
|
8
|
+
# major version.
|
|
9
|
+
class Component < JetUi::Dialog::Component
|
|
10
|
+
def self.deprecator
|
|
11
|
+
@deprecator ||= ActiveSupport::Deprecation.new('1.0', 'JetUi')
|
|
47
12
|
end
|
|
48
13
|
|
|
49
|
-
def
|
|
50
|
-
|
|
14
|
+
def initialize(title: nil, subtitle: nil, size: JetUi::Dialog::Component::DEFAULT_SIZE, id: nil)
|
|
15
|
+
self.class.deprecator.warn(
|
|
16
|
+
'JetUi::Modal::Component is deprecated and will be removed in the next major ' \
|
|
17
|
+
'version. Use JetUi::Dialog::Component with position: :center instead ' \
|
|
18
|
+
'(jet_ui.dialog).'
|
|
19
|
+
)
|
|
20
|
+
super(title: title, subtitle: subtitle, position: :center, size: size, id: id)
|
|
51
21
|
end
|
|
52
22
|
end
|
|
53
23
|
end
|
|
@@ -2,44 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Modal
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@direction = direction
|
|
8
|
-
@align = align
|
|
9
|
-
@justify = justify
|
|
10
|
-
@bordered = bordered
|
|
11
|
-
@options = options
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call
|
|
15
|
-
content_tag :div, content, class: classes, **@options.except(:class)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def classes
|
|
21
|
-
class_names(
|
|
22
|
-
'modal__footer',
|
|
23
|
-
{ 'modal__footer-bordered' => @bordered },
|
|
24
|
-
direction_class,
|
|
25
|
-
align_class,
|
|
26
|
-
justify_class,
|
|
27
|
-
@options[:class]
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def direction_class
|
|
32
|
-
{ col: 'flex flex-col gap-2', row: 'flex flex-row gap-2' }[@direction]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def align_class
|
|
36
|
-
{ start: 'items-start', center: 'items-center', end: 'items-end' }[@align]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def justify_class
|
|
40
|
-
{ start: 'justify-start', center: 'justify-center', end: 'justify-end',
|
|
41
|
-
between: 'justify-between' }[@justify]
|
|
42
|
-
end
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::FooterComponent} instead.
|
|
6
|
+
class FooterComponent < JetUi::Dialog::FooterComponent
|
|
43
7
|
end
|
|
44
8
|
end
|
|
45
9
|
end
|
|
@@ -2,44 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module JetUi
|
|
4
4
|
module Modal
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@bordered = bordered
|
|
12
|
-
@options = options
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
erb_template <<~ERB
|
|
16
|
-
<div class="<%= classes %>">
|
|
17
|
-
<div>
|
|
18
|
-
<% if @title %>
|
|
19
|
-
<h3 class="modal__title"><%= @title %></h3>
|
|
20
|
-
<% end %>
|
|
21
|
-
<% if @subtitle %>
|
|
22
|
-
<div class="modal__subtitle"><%= @subtitle %></div>
|
|
23
|
-
<% end %>
|
|
24
|
-
<%= content %>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<% if @closable %>
|
|
28
|
-
<button type="button" class="modal__close" data-action="click->modal#close click->modals#close" aria-label="Close" data-id="<%= @id %>">
|
|
29
|
-
<%= helpers.jet_ui.icon("x-mark", size: 6) %>
|
|
30
|
-
</button>
|
|
31
|
-
<% end %>
|
|
32
|
-
</div>
|
|
33
|
-
ERB
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def classes
|
|
38
|
-
class_names(
|
|
39
|
-
'modal__header',
|
|
40
|
-
{ 'modal__header-bordered' => @bordered },
|
|
41
|
-
@options[:class]
|
|
42
|
-
)
|
|
5
|
+
# @deprecated Use {JetUi::Dialog::HeaderComponent} instead.
|
|
6
|
+
class HeaderComponent < JetUi::Dialog::HeaderComponent
|
|
7
|
+
# `id:` accepted and ignored for signature compatibility with the pre-deprecation API.
|
|
8
|
+
def initialize(title: nil, subtitle: nil, closable: true, id: nil, bordered: true, # rubocop:disable Lint/UnusedMethodArgument
|
|
9
|
+
**options)
|
|
10
|
+
super(title: title, subtitle: subtitle, closable: closable, bordered: bordered, **options)
|
|
43
11
|
end
|
|
44
12
|
end
|
|
45
13
|
end
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
<dialog id="turbo-confirm" tabindex="-1"
|
|
2
|
-
class="
|
|
2
|
+
class="dialog dialog-center w-2xl"
|
|
3
3
|
data-controller="turbo-confirm">
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
<h3 class="modal__title">Are you absolutely sure?</h3>
|
|
8
|
-
</div>
|
|
9
|
-
</div>
|
|
4
|
+
<div class="dialog__panel">
|
|
5
|
+
<form method="dialog">
|
|
6
|
+
<%= helpers.jet_ui.dialog_header(title: 'Are you absolutely sure?', closable: false) %>
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
<%= helpers.jet_ui.dialog_body do %>
|
|
9
|
+
<p>This cannot be undone.</p>
|
|
10
|
+
<% end %>
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
<%= helpers.jet_ui.dialog_footer justify: :end do %>
|
|
13
|
+
<%= helpers.jet_ui.btn 'Cancel', type: :submit, variant: :outline, value: 'cancel' %>
|
|
14
|
+
<%= helpers.jet_ui.btn "Yes, I'm sure", type: :submit, variant: :danger, value: 'confirm' %>
|
|
15
|
+
<% end %>
|
|
16
|
+
</form>
|
|
17
|
+
</div>
|
|
20
18
|
</dialog>
|