hakumi_components 0.1.16.pre → 0.1.17.pre

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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +169 -23
  3. data/app/assets/javascripts/hakumi_components.js +12 -12
  4. data/app/assets/stylesheets/hakumi_components.css +1 -1
  5. data/app/components/hakumi/alert/component.html.erb +12 -8
  6. data/app/components/hakumi/alert/component.rb +18 -62
  7. data/app/components/hakumi/base_component.rb +13 -0
  8. data/app/components/hakumi/card/component.html.erb +14 -22
  9. data/app/components/hakumi/card/component.rb +38 -31
  10. data/app/components/hakumi/checkbox/component.html.erb +39 -21
  11. data/app/components/hakumi/checkbox/component.rb +12 -2
  12. data/app/components/hakumi/collapse/component.html.erb +2 -2
  13. data/app/components/hakumi/collapse/component.rb +1 -1
  14. data/app/components/hakumi/collapse/panel/component.rb +9 -0
  15. data/app/components/hakumi/color_picker/component.rb +0 -4
  16. data/app/components/hakumi/drawer/component.html.erb +7 -7
  17. data/app/components/hakumi/drawer/component.rb +12 -19
  18. data/app/components/hakumi/input/component.rb +0 -2
  19. data/app/components/hakumi/input/text_area/component.rb +0 -2
  20. data/app/components/hakumi/input_number/component.rb +3 -4
  21. data/app/components/hakumi/mentions/component.rb +0 -1
  22. data/app/components/hakumi/modal/component.html.erb +40 -0
  23. data/app/components/hakumi/modal/component.rb +24 -102
  24. data/app/components/hakumi/modal/confirm/component.html.erb +23 -0
  25. data/app/components/hakumi/modal/confirm/component.rb +23 -41
  26. data/app/components/hakumi/modal/error/component.rb +12 -11
  27. data/app/components/hakumi/modal/info/component.rb +12 -11
  28. data/app/components/hakumi/modal/success/component.rb +12 -11
  29. data/app/components/hakumi/modal/warning/component.rb +15 -10
  30. data/app/components/hakumi/popconfirm/component.html.erb +25 -25
  31. data/app/components/hakumi/popconfirm/component.rb +11 -27
  32. data/app/components/hakumi/rate/component.rb +0 -1
  33. data/app/components/hakumi/segmented/component.rb +0 -4
  34. data/app/components/hakumi/slider/component.rb +2 -6
  35. data/app/components/hakumi/statistic/component.rb +0 -4
  36. data/app/components/hakumi/switch/component.html.erb +4 -0
  37. data/app/components/hakumi/switch/component.rb +1 -2
  38. data/app/components/hakumi/table/component.rb +3 -229
  39. data/app/components/hakumi/table/concerns/columns.rb +1 -1
  40. data/app/components/hakumi/table/concerns/editable.rb +121 -0
  41. data/app/components/hakumi/table/concerns/ellipsis.rb +63 -0
  42. data/app/components/hakumi/table/concerns/fixed_columns.rb +87 -0
  43. data/app/components/hakumi/transfer/component.rb +0 -4
  44. data/app/controllers/{hakumi_components → hakumi}/components_controller.rb +2 -2
  45. data/app/form_builders/hakumi/form_builder.rb +217 -175
  46. data/app/helpers/hakumi/form_helper.rb +39 -0
  47. data/app/javascript/hakumi_components/controllers/base/registry_controller.js +83 -3
  48. data/app/javascript/hakumi_components/controllers/hakumi/affix_controller.js +0 -23
  49. data/app/javascript/hakumi_components/controllers/hakumi/alert_controller.js +2 -1
  50. data/app/javascript/hakumi_components/controllers/hakumi/button_controller.js +0 -7
  51. data/app/javascript/hakumi_components/controllers/hakumi/calendar_controller.js +0 -2
  52. data/app/javascript/hakumi_components/controllers/hakumi/color_picker_controller.js +1 -6
  53. data/app/javascript/hakumi_components/controllers/hakumi/date_picker_controller.js +28 -34
  54. data/app/javascript/hakumi_components/controllers/hakumi/drawer_controller.js +2 -1
  55. data/app/javascript/hakumi_components/controllers/hakumi/form_item_controller.js +9 -63
  56. data/app/javascript/hakumi_components/controllers/hakumi/mentions_controller.js +4 -11
  57. data/app/javascript/hakumi_components/controllers/hakumi/message_controller.js +1 -1
  58. data/app/javascript/hakumi_components/controllers/hakumi/modal_controller.js +4 -20
  59. data/app/javascript/hakumi_components/controllers/hakumi/notification_controller.js +1 -1
  60. data/app/javascript/hakumi_components/controllers/hakumi/popconfirm_controller.js +33 -27
  61. data/app/javascript/hakumi_components/controllers/hakumi/popover_controller.js +2 -23
  62. data/app/javascript/hakumi_components/controllers/hakumi/qr_code_controller.js +0 -20
  63. data/app/javascript/hakumi_components/controllers/hakumi/segmented_controller.js +0 -2
  64. data/app/javascript/hakumi_components/controllers/hakumi/spin_controller.js +1 -19
  65. data/app/javascript/hakumi_components/controllers/hakumi/statistic_controller.js +0 -2
  66. data/app/javascript/hakumi_components/controllers/hakumi/table_controller.js +48 -74
  67. data/app/javascript/hakumi_components/controllers/hakumi/tag_controller.js +15 -14
  68. data/app/javascript/hakumi_components/controllers/hakumi/tag_group_controller.js +14 -13
  69. data/app/javascript/hakumi_components/controllers/hakumi/theme_controller.js +24 -1
  70. data/app/javascript/hakumi_components/controllers/hakumi/time_picker_controller.js +3 -7
  71. data/app/javascript/hakumi_components/controllers/hakumi/timeline_controller.js +0 -16
  72. data/app/javascript/hakumi_components/controllers/hakumi/transfer_controller.js +2 -2
  73. data/app/javascript/hakumi_components/controllers/hakumi/tree_controller.js +0 -2
  74. data/app/javascript/hakumi_components/controllers/hakumi/tree_select_controller.js +3 -3
  75. data/app/javascript/hakumi_components/controllers/hakumi/upload_controller.js +12 -26
  76. data/app/javascript/hakumi_components/core/persistence.js +3 -3
  77. data/app/javascript/hakumi_components/core/render_component.js +3 -1
  78. data/app/javascript/lib/validation_manager.js +101 -0
  79. data/app/javascript/stylesheets/_theme-tokens.scss +2 -1
  80. data/app/javascript/stylesheets/components/_modal.scss +13 -0
  81. data/app/services/{hakumi_components → hakumi}/component_handler.rb +1 -1
  82. data/app/services/hakumi/icon/loader.rb +2 -2
  83. data/app/services/hakumi/illustrations/loader.rb +3 -3
  84. data/app/views/hakumi/_drawer.html.erb +21 -0
  85. data/app/views/hakumi/_modal.html.erb +18 -0
  86. data/lib/hakumi_components/documentation.rb +127 -0
  87. data/lib/hakumi_components/engine.rb +13 -4
  88. data/lib/hakumi_components/rails/attribute_introspection.rb +1 -1
  89. data/lib/hakumi_components/rails/validation_introspection.rb +5 -5
  90. data/lib/hakumi_components/rails/validation_mapper.rb +484 -0
  91. data/lib/hakumi_components/rails.rb +2 -1
  92. data/lib/hakumi_components/version.rb +2 -2
  93. data/lib/hakumi_components.rb +3 -1
  94. data/lib/tasks/coverage.rake +37 -0
  95. data/sig/hakumi/base_component.rbs +5 -0
  96. data/sig/hakumi/checkbox/component.rbs +10 -0
  97. data/sig/hakumi/color_picker/component.rbs +0 -1
  98. data/sig/hakumi/form_builder.rbs +9 -1
  99. data/sig/{hakumi_components → hakumi}/rails/attribute_introspection.rbs +1 -1
  100. data/sig/{hakumi_components → hakumi}/rails/validation_introspection.rbs +1 -1
  101. data/sig/hakumi/rails/validation_mapper.rbs +53 -0
  102. data/sig/{hakumi_components → hakumi}/rails.rbs +1 -1
  103. data/sig/hakumi/segmented/component.rbs +0 -1
  104. data/sig/hakumi/slider/component.rbs +0 -1
  105. data/sig/hakumi/statistic/component.rbs +0 -2
  106. data/sig/hakumi/table/component.rbs +3 -4
  107. data/sig/hakumi/table/concerns/columns.rbs +2 -1
  108. data/sig/hakumi/table/concerns/editable.rbs +40 -0
  109. data/sig/hakumi/table/concerns/ellipsis.rbs +27 -0
  110. data/sig/hakumi/table/concerns/fixed_columns.rbs +33 -0
  111. data/sig/hakumi/transfer/component.rbs +0 -1
  112. data/sig/{hakumi_components.rbs → hakumi.rbs} +20 -3
  113. data/sig/rails/active_model/validations/comparison_validator.rbs +6 -0
  114. metadata +44 -29
  115. data/app/views/hakumi_components/_drawer.html.erb +0 -3
  116. data/app/views/hakumi_components/_modal.html.erb +0 -3
  117. /data/app/views/{hakumi_components → hakumi}/_admin_panel.html.erb +0 -0
  118. /data/app/views/{hakumi_components → hakumi}/_affix.html.erb +0 -0
  119. /data/app/views/{hakumi_components → hakumi}/_alert.html.erb +0 -0
  120. /data/app/views/{hakumi_components → hakumi}/_confirm.html.erb +0 -0
  121. /data/app/views/{hakumi_components → hakumi}/_message.html.erb +0 -0
  122. /data/app/views/{hakumi_components → hakumi}/_notification.html.erb +0 -0
  123. /data/app/views/{hakumi_components → hakumi}/_popconfirm.html.erb +0 -0
  124. /data/app/views/{hakumi_components → hakumi}/_popover.html.erb +0 -0
  125. /data/app/views/{hakumi_components → hakumi}/_qr_code.html.erb +0 -0
  126. /data/app/views/{hakumi_components → hakumi}/_result.html.erb +0 -0
  127. /data/app/views/{hakumi_components → hakumi}/_segmented.html.erb +0 -0
  128. /data/app/views/{hakumi_components → hakumi}/_skeleton.html.erb +0 -0
  129. /data/app/views/{hakumi_components → hakumi}/_spin.html.erb +0 -0
  130. /data/app/views/{hakumi_components → hakumi}/_statistic.html.erb +0 -0
  131. /data/app/views/{hakumi_components → hakumi}/_table.html.erb +0 -0
  132. /data/app/views/{hakumi_components → hakumi}/_tag.html.erb +0 -0
  133. /data/app/views/{hakumi_components → hakumi}/_timeline.html.erb +0 -0
  134. /data/app/views/{hakumi_components → hakumi}/_tree.html.erb +0 -0
@@ -116,7 +116,6 @@ module Hakumi
116
116
  placeholder: @placeholder,
117
117
  disabled: @disabled ? true : nil,
118
118
  readonly: @readonly ? true : nil,
119
- required: @required ? true : nil,
120
119
  "aria-invalid": has_error? ? "true" : nil,
121
120
  "aria-describedby": describedby_ids,
122
121
  data: {
@@ -0,0 +1,40 @@
1
+ <%= content_tag(:div, class: classes, style: style, data: data_attributes, **@html_attributes.except(:class, :style, :data)) do %>
2
+ <% if @mask %>
3
+ <div class="hakumi-modal-mask" data-hakumi--modal-target="mask" data-action="click->hakumi--modal#handleMaskClick"></div>
4
+ <% end %>
5
+
6
+ <div class="hakumi-modal-wrap" tabindex="-1" data-hakumi--modal-target="wrapper" data-action="keydown->hakumi--modal#handleKeydown click->hakumi--modal#handleWrapperClick">
7
+ <div class="<%= modal_classes %>" style="<%= modal_style %>" role="dialog" aria-modal="true">
8
+ <div class="hakumi-modal-content">
9
+ <% if @closable %>
10
+ <button type="button" class="hakumi-modal-close" aria-label="Close" data-hakumi-action="close">
11
+ <span class="hakumi-modal-close-x">
12
+ <%= render Hakumi::Icon::Component.new(name: :close) %>
13
+ </span>
14
+ </button>
15
+ <% end %>
16
+
17
+ <% if render_header? %>
18
+ <div class="hakumi-modal-header">
19
+ <% if header? %>
20
+ <div class="hakumi-modal-title"><%= header %></div>
21
+ <% end %>
22
+ <% if extra? %>
23
+ <div class="hakumi-modal-extra"><%= extra %></div>
24
+ <% end %>
25
+ </div>
26
+ <% end %>
27
+
28
+ <div class="hakumi-modal-body">
29
+ <%= body_content %>
30
+ </div>
31
+
32
+ <% if render_footer? %>
33
+ <div class="hakumi-modal-footer">
34
+ <%= footer %>
35
+ </div>
36
+ <% end %>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ <% end %>
@@ -3,73 +3,53 @@
3
3
  module Hakumi
4
4
  module Modal
5
5
  class Component < Hakumi::BaseComponent
6
- # Extracts locals from controller params for dynamic rendering
6
+ # Slots for content
7
+ renders_one :header
8
+ renders_one :body
9
+ renders_one :footer
10
+ renders_one :extra
11
+
12
+ # Extracts locals from controller params for programmatic rendering
7
13
  # @param params [ActionController::Parameters]
8
14
  # @return [Hash] Arguments for initialize
9
15
  def self.extract_controller_locals(params)
10
16
  {
11
- title: params[:title].presence || "Modal",
12
- message: params[:message].presence || params[:body].presence || "Generated modal content.",
17
+ title: params[:title],
18
+ message: params[:message],
13
19
  open: ActiveModel::Type::Boolean.new.cast(params[:open]),
14
- ok_text: params[:ok_text].presence || "OK",
15
- cancel_text: params[:cancel_text].presence || "Cancel"
20
+ width: params[:width]&.to_i,
21
+ centered: ActiveModel::Type::Boolean.new.cast(params[:centered]),
22
+ closable: ActiveModel::Type::Boolean.new.cast(params[:closable]),
23
+ mask: ActiveModel::Type::Boolean.new.cast(params[:mask]),
24
+ mask_closable: ActiveModel::Type::Boolean.new.cast(params[:mask_closable]),
25
+ keyboard: ActiveModel::Type::Boolean.new.cast(params[:keyboard]),
26
+ confirm_loading: ActiveModel::Type::Boolean.new.cast(params[:confirm_loading])
16
27
  }
17
28
  end
29
+
18
30
  def initialize(
19
31
  open: false,
20
- title: nil,
21
32
  width: 520,
22
33
  centered: false,
23
- footer: nil,
24
34
  closable: true,
25
35
  mask: true,
26
36
  mask_closable: true,
27
37
  keyboard: true,
28
- on_ok: nil,
29
- on_cancel: nil,
30
38
  confirm_loading: false,
31
- ok_text: "OK",
32
- cancel_text: "Cancel",
33
- ok_button_props: {},
34
- cancel_button_props: {},
35
39
  **html_attributes
36
40
  )
37
41
  @open = open
38
- @title = title
39
42
  @width = width
40
43
  @centered = centered
41
- @footer = footer
42
44
  @closable = closable
43
45
  @mask = mask
44
46
  @mask_closable = mask_closable
45
47
  @keyboard = keyboard
46
- @on_ok = on_ok
47
- @on_cancel = on_cancel
48
48
  @confirm_loading = confirm_loading
49
- @ok_text = ok_text
50
- @cancel_text = cancel_text
51
- @ok_button_props = ok_button_props || {}
52
- @cancel_button_props = cancel_button_props || {}
53
49
  @html_attributes = html_attributes
54
50
  super()
55
51
  end
56
52
 
57
- def call
58
- # Merge html_attributes with our default attributes
59
- options = @html_attributes.merge(
60
- class: classes,
61
- style: style,
62
- data: data_attributes
63
- )
64
-
65
- content_tag(:div, options) do
66
- safe_join([
67
- render_mask,
68
- render_wrapper
69
- ])
70
- end
71
- end
72
-
73
53
  private
74
54
 
75
55
  def classes
@@ -92,27 +72,6 @@ module Hakumi
92
72
  }.merge(@html_attributes[:data] || {})
93
73
  end
94
74
 
95
- def render_mask
96
- return unless @mask
97
-
98
- content_tag(:div, "", class: "hakumi-modal-mask", data: { hakumi__modal_target: "mask", action: "click->hakumi--modal#handleMaskClick" })
99
- end
100
-
101
- def render_wrapper
102
- content_tag(:div, class: "hakumi-modal-wrap", tabindex: -1, data: { hakumi__modal_target: "wrapper", action: "keydown->hakumi--modal#handleKeydown click->hakumi--modal#handleWrapperClick" }) do
103
- content_tag(:div, class: modal_classes, style: modal_style, role: "dialog", aria: { modal: true }) do
104
- content_tag(:div, class: "hakumi-modal-content") do
105
- safe_join([
106
- render_close_icon,
107
- render_header,
108
- render_body,
109
- render_footer
110
- ])
111
- end
112
- end
113
- end
114
- end
115
-
116
75
  def modal_classes
117
76
  classes = [ "hakumi-modal" ]
118
77
  classes << "hakumi-modal-centered" if @centered
@@ -123,54 +82,17 @@ module Hakumi
123
82
  "width: #{@width}px;"
124
83
  end
125
84
 
126
- def render_close_icon
127
- return unless @closable
128
-
129
- content_tag(:button, type: "button", class: "hakumi-modal-close", aria: { label: "Close" }, data: { action: "click->hakumi--modal#close" }) do
130
- content_tag(:span, class: "hakumi-modal-close-x") do
131
- render Hakumi::Icon::Component.new(name: :close)
132
- end
133
- end
134
- end
135
-
136
- def render_header
137
- return if @title.blank?
138
-
139
- content_tag(:div, class: "hakumi-modal-header") do
140
- content_tag(:div, @title, class: "hakumi-modal-title")
141
- end
142
- end
143
-
144
- def render_body
145
- content_tag(:div, content, class: "hakumi-modal-body")
85
+ def render_header?
86
+ header? || @closable || extra?
146
87
  end
147
88
 
148
- def render_footer
149
- return if @footer == false
150
-
151
- content_tag(:div, class: "hakumi-modal-footer") do
152
- if @footer.present?
153
- @footer
154
- else
155
- default_footer
156
- end
157
- end
89
+ def render_footer?
90
+ footer?
158
91
  end
159
92
 
160
- def default_footer
161
- safe_join([
162
- render(Hakumi::Button::Component.new(
163
- type: :default,
164
- **@cancel_button_props.except(:data),
165
- data: { "hakumi-modal-close": true }.merge(@cancel_button_props[:data] || {})
166
- )) { @cancel_text },
167
- render(Hakumi::Button::Component.new(
168
- type: :primary,
169
- loading: @confirm_loading,
170
- **@ok_button_props.except(:data),
171
- data: { "hakumi-modal-ok": true }.merge(@ok_button_props[:data] || {})
172
- )) { @ok_text }
173
- ])
93
+ # Content resolution: body slot > block content
94
+ def body_content
95
+ body? ? body : content
174
96
  end
175
97
  end
176
98
  end
@@ -0,0 +1,23 @@
1
+ <%= render Hakumi::Modal::Component.new(
2
+ id: @id,
3
+ open: @open,
4
+ mask_closable: false,
5
+ closable: false,
6
+ **@html_attributes
7
+ ) do |modal| %>
8
+ <% modal.with_header do %>
9
+ <%= @title %>
10
+ <% end %>
11
+
12
+ <div class="hakumi-modal-confirm-body-wrapper">
13
+ <%= render Hakumi::Icon::Component.new(name: icon_name, theme: :filled, color: icon_color, size: 22) %>
14
+ <div class="hakumi-modal-confirm-content">
15
+ <p><%= content %></p>
16
+ </div>
17
+ </div>
18
+
19
+ <% modal.with_footer do %>
20
+ <%= render(Hakumi::Button::Component.new(data: { "hakumi-action": "cancel" })) { "Cancel" } %>
21
+ <%= render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-action": "confirm" })) { "OK" } %>
22
+ <% end %>
23
+ <% end %>
@@ -4,58 +4,40 @@ module Hakumi
4
4
  module Modal
5
5
  module Confirm
6
6
  class Component < Hakumi::BaseComponent
7
- # Extracts locals from controller params for dynamic rendering
8
- # @param params [ActionController::Parameters]
9
- # @return [Hash] Arguments for initialize
10
- def self.extract_controller_locals(params)
11
- {
12
- title: params[:title].presence || "Confirm",
13
- message: params[:message].presence || params[:body].presence || "Generated confirm content.",
14
- open: ActiveModel::Type::Boolean.new.cast(params[:open]),
15
- ok_text: params[:ok_text].presence || "OK",
16
- cancel_text: params[:cancel_text].presence || "Cancel"
17
- }
18
- end
19
7
  def initialize(
20
8
  id:,
21
- title: "Confirm",
22
- message: nil,
23
9
  open: false,
24
- ok_text: "OK",
25
- cancel_text: "Cancel",
10
+ title: "Confirm",
11
+ type: :confirm,
26
12
  **html_attributes
27
13
  )
28
14
  @id = id
29
- @title = title
30
- @message = message
31
15
  @open = open
32
- @ok_text = ok_text
33
- @cancel_text = cancel_text
16
+ @title = title
17
+ @type = type
34
18
  @html_attributes = html_attributes
35
19
  super()
36
20
  end
37
21
 
38
- def call
39
- render(Hakumi::Modal::Component.new(
40
- id: @id,
41
- title: @title,
42
- open: @open,
43
- mask_closable: false,
44
- ok_text: @ok_text,
45
- cancel_text: @cancel_text,
46
- ok_button_props: { data: { "hakumi-modal-close": true } },
47
- on_ok: "hakumi--modal#close",
48
- on_cancel: "hakumi--modal#close",
49
- **@html_attributes
50
- )) do
51
- content_tag(:div, style: "display: flex; align-items: flex-start; gap: 12px;") do
52
- safe_join([
53
- render(Hakumi::Icon::Component.new(name: :exclamation_circle, theme: :filled, color: "#faad14", size: 22)),
54
- content_tag(:div) do
55
- content_tag(:p, @message || content, style: "margin: 0;")
56
- end
57
- ])
58
- end
22
+ private
23
+
24
+ def icon_name
25
+ case @type
26
+ when :info then :info_circle
27
+ when :success then :check_circle
28
+ when :error then :close_circle
29
+ when :warning then :exclamation_circle
30
+ else :exclamation_circle
31
+ end
32
+ end
33
+
34
+ def icon_color
35
+ case @type
36
+ when :info then "#1890ff"
37
+ when :success then "#52c41a"
38
+ when :error then "#ff4d4f"
39
+ when :warning then "#faad14"
40
+ else "#faad14"
59
41
  end
60
42
  end
61
43
  end
@@ -22,23 +22,24 @@ module Hakumi
22
22
  end
23
23
 
24
24
  def call
25
- footer_content = capture do
26
- render(Hakumi::Button::Component.new(type: :primary, danger: true, data: { "hakumi-modal-close": true })) { @ok_text }
27
- end
28
-
29
25
  render(Hakumi::Modal::Component.new(
30
26
  id: @id,
31
- title: @title,
32
27
  open: @open,
33
- footer: footer_content,
34
- on_ok: "hakumi--modal#close",
28
+ closable: false,
29
+ mask_closable: false,
35
30
  **@html_attributes
36
- )) do
37
- content_tag(:div, style: "display: flex; align-items: flex-start; gap: 12px;") do
31
+ )) do |modal|
32
+ modal.with_header { @title }
33
+
34
+ modal.with_footer do
35
+ render(Hakumi::Button::Component.new(type: :primary, danger: true, data: { "hakumi-action": "close" })) { @ok_text }
36
+ end
37
+
38
+ content_tag(:div, class: "hakumi-modal-confirm-body-wrapper") do
38
39
  safe_join([
39
40
  render(Hakumi::Icon::Component.new(name: :close_circle, theme: :filled, color: "#ff4d4f", size: 22)),
40
- content_tag(:div) do
41
- content_tag(:p, @message || content, style: "margin: 0;")
41
+ content_tag(:div, class: "hakumi-modal-confirm-content") do
42
+ content_tag(:p, @message || content)
42
43
  end
43
44
  ])
44
45
  end
@@ -22,23 +22,24 @@ module Hakumi
22
22
  end
23
23
 
24
24
  def call
25
- footer_content = capture do
26
- render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-modal-close": true })) { @ok_text }
27
- end
28
-
29
25
  render(Hakumi::Modal::Component.new(
30
26
  id: @id,
31
- title: @title,
32
27
  open: @open,
33
- footer: footer_content,
34
- on_ok: "hakumi--modal#close",
28
+ closable: false,
29
+ mask_closable: false,
35
30
  **@html_attributes
36
- )) do
37
- content_tag(:div, style: "display: flex; align-items: flex-start; gap: 12px;") do
31
+ )) do |modal|
32
+ modal.with_header { @title }
33
+
34
+ modal.with_footer do
35
+ render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-action": "close" })) { @ok_text }
36
+ end
37
+
38
+ content_tag(:div, class: "hakumi-modal-confirm-body-wrapper") do
38
39
  safe_join([
39
40
  render(Hakumi::Icon::Component.new(name: :info_circle, theme: :filled, color: "#1890ff", size: 22)),
40
- content_tag(:div) do
41
- content_tag(:p, @message || content, style: "margin: 0;")
41
+ content_tag(:div, class: "hakumi-modal-confirm-content") do
42
+ content_tag(:p, @message || content)
42
43
  end
43
44
  ])
44
45
  end
@@ -22,23 +22,24 @@ module Hakumi
22
22
  end
23
23
 
24
24
  def call
25
- footer_content = capture do
26
- render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-modal-close": true })) { @ok_text }
27
- end
28
-
29
25
  render(Hakumi::Modal::Component.new(
30
26
  id: @id,
31
- title: @title,
32
27
  open: @open,
33
- footer: footer_content,
34
- on_ok: "hakumi--modal#close",
28
+ closable: false,
29
+ mask_closable: false,
35
30
  **@html_attributes
36
- )) do
37
- content_tag(:div, style: "display: flex; align-items: flex-start; gap: 12px;") do
31
+ )) do |modal|
32
+ modal.with_header { @title }
33
+
34
+ modal.with_footer do
35
+ render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-action": "close" })) { @ok_text }
36
+ end
37
+
38
+ content_tag(:div, class: "hakumi-modal-confirm-body-wrapper") do
38
39
  safe_join([
39
40
  render(Hakumi::Icon::Component.new(name: :check_circle, theme: :filled, color: "#52c41a", size: 22)),
40
- content_tag(:div) do
41
- content_tag(:p, @message || content, style: "margin: 0;")
41
+ content_tag(:div, class: "hakumi-modal-confirm-content") do
42
+ content_tag(:p, @message || content)
42
43
  end
43
44
  ])
44
45
  end
@@ -26,20 +26,25 @@ module Hakumi
26
26
  def call
27
27
  render(Hakumi::Modal::Component.new(
28
28
  id: @id,
29
- title: @title,
30
29
  open: @open,
31
- ok_text: @ok_text,
32
- cancel_text: @cancel_text,
33
- ok_button_props: { data: { "hakumi-modal-close": true } },
34
- on_ok: "hakumi--modal#close",
35
- on_cancel: "hakumi--modal#close",
30
+ closable: false,
31
+ mask_closable: false,
36
32
  **@html_attributes
37
- )) do
38
- content_tag(:div, style: "display: flex; align-items: flex-start; gap: 12px;") do
33
+ )) do |modal|
34
+ modal.with_header { @title }
35
+
36
+ modal.with_footer do
37
+ safe_join([
38
+ render(Hakumi::Button::Component.new(data: { "hakumi-action": "cancel" })) { @cancel_text },
39
+ render(Hakumi::Button::Component.new(type: :primary, data: { "hakumi-action": "confirm" })) { @ok_text }
40
+ ])
41
+ end
42
+
43
+ content_tag(:div, class: "hakumi-modal-confirm-body-wrapper") do
39
44
  safe_join([
40
45
  render(Hakumi::Icon::Component.new(name: :warning, theme: :filled, color: "#faad14", size: 22)),
41
- content_tag(:div) do
42
- content_tag(:p, @message || content, style: "margin: 0;")
46
+ content_tag(:div, class: "hakumi-modal-confirm-content") do
47
+ content_tag(:p, @message || content)
43
48
  end
44
49
  ])
45
50
  end
@@ -1,10 +1,10 @@
1
- <div class="<%= wrapper_classes %>" data-controller="hakumi--popconfirm" <%= tag.attributes(data: data_attributes) %> <%= tag.attributes(@html_options.except(:class, :data)) %>>
1
+ <div class="<%= wrapper_classes %>" <%= tag.attributes(data: data_attributes.merge(@html_options[:data] || {})) %> <%= tag.attributes(@html_options.except(:class, :data)) %>>
2
2
  <span class="hakumi-popconfirm-trigger" data-hakumi--popconfirm-target="trigger">
3
3
  <%= content %>
4
4
  </span>
5
5
 
6
- <div class="hakumi-popconfirm"
7
- data-hakumi--popconfirm-target="popover"
6
+ <div class="hakumi-popconfirm"
7
+ data-hakumi--popconfirm-target="popover"
8
8
  role="tooltip"
9
9
  style="display: none;">
10
10
  <div class="hakumi-popconfirm-content">
@@ -13,40 +13,40 @@
13
13
  <div class="hakumi-popconfirm-inner-content">
14
14
  <div class="hakumi-popconfirm-message">
15
15
  <span class="hakumi-popconfirm-message-icon">
16
- <% if @icon %>
17
- <%= @icon %>
16
+ <% if icon? %>
17
+ <%= icon %>
18
18
  <% else %>
19
- <%= render Hakumi::Icon::Component.new(name: "exclamation-circle", theme: :filled) %>
19
+ <%= default_icon_element %>
20
20
  <% end %>
21
21
  </span>
22
- <div class="hakumi-popconfirm-title"><%= @title %></div>
22
+ <% if title? %>
23
+ <div class="hakumi-popconfirm-title"><%= title %></div>
24
+ <% end %>
23
25
  </div>
24
-
25
- <% if @description %>
26
+
27
+ <% if description? %>
26
28
  <div class="hakumi-popconfirm-description">
27
- <%= @description %>
29
+ <%= description %>
28
30
  </div>
29
31
  <% end %>
30
32
 
31
33
  <div class="hakumi-popconfirm-buttons">
32
- <% if @show_cancel %>
34
+ <% if buttons? %>
35
+ <%= buttons %>
36
+ <% else %>
37
+ <% if @show_cancel %>
38
+ <%= render(Hakumi::Button::Component.new(
39
+ size: :small,
40
+ data: { "hakumi-action": "cancel" }
41
+ )) { "Cancel" } %>
42
+ <% end %>
43
+
33
44
  <%= render(Hakumi::Button::Component.new(
45
+ type: @ok_type,
34
46
  size: :small,
35
- data: {
36
- action: "click->hakumi--popconfirm#cancel",
37
- hakumi__popconfirm_target: "cancelButton"
38
- }
39
- )) { @cancel_text } %>
47
+ data: { "hakumi-action": "confirm" }
48
+ )) { "OK" } %>
40
49
  <% end %>
41
-
42
- <%= render(Hakumi::Button::Component.new(
43
- type: @ok_type,
44
- size: :small,
45
- data: {
46
- action: "click->hakumi--popconfirm#confirm",
47
- hakumi__popconfirm_target: "okButton"
48
- }
49
- )) { @ok_text } %>
50
50
  </div>
51
51
  </div>
52
52
  </div>
@@ -13,46 +13,26 @@ module Hakumi
13
13
 
14
14
  TRIGGERS = %w[click hover focus].freeze
15
15
 
16
- def self.extract_controller_locals(params)
17
- {
18
- title: params[:title],
19
- description: params[:description],
20
- ok_text: params[:ok_text],
21
- cancel_text: params[:cancel_text],
22
- ok_type: params[:ok_type],
23
- placement: params[:placement],
24
- trigger: params[:trigger],
25
- disabled: params[:disabled],
26
- show_cancel: params[:show_cancel] != false,
27
- icon: params[:icon],
28
- auto_adjust_overflow: params[:auto_adjust_overflow] != false
29
- }
30
- end
16
+ # Slots for content
17
+ renders_one :icon
18
+ renders_one :title
19
+ renders_one :description
20
+ renders_one :buttons
31
21
 
32
22
  def initialize(
33
- title: nil,
34
- description: nil,
35
- ok_text: "OK",
36
- cancel_text: "Cancel",
37
- ok_type: :primary,
38
23
  placement: "top",
39
24
  trigger: "click",
40
25
  disabled: false,
26
+ ok_type: :primary,
41
27
  show_cancel: true,
42
- icon: nil,
43
28
  auto_adjust_overflow: true,
44
29
  **html_options
45
30
  )
46
- @title = title
47
- @description = description
48
- @ok_text = ok_text
49
- @cancel_text = cancel_text
50
- @ok_type = ok_type
51
31
  @placement = placement
52
32
  @trigger = trigger
53
33
  @disabled = disabled
34
+ @ok_type = ok_type
54
35
  @show_cancel = show_cancel
55
- @icon = icon
56
36
  @auto_adjust_overflow = auto_adjust_overflow
57
37
  @html_options = html_options
58
38
 
@@ -83,6 +63,10 @@ module Hakumi
83
63
  validate_inclusion!(:placement, PLACEMENTS)
84
64
  validate_inclusion!(:trigger, TRIGGERS)
85
65
  end
66
+
67
+ def default_icon_element
68
+ render Hakumi::Icon::Component.new(name: "exclamation-circle", theme: :filled)
69
+ end
86
70
  end
87
71
  end
88
72
  end
@@ -119,7 +119,6 @@ module Hakumi
119
119
  id: input_id,
120
120
  value: current_value,
121
121
  disabled: @disabled ? true : nil,
122
- required: @required ? true : nil,
123
122
  "aria-invalid": has_error? ? "true" : nil,
124
123
  "aria-describedby": describedby_ids,
125
124
  data: {
@@ -236,10 +236,6 @@ module Hakumi
236
236
  symbol == :default ? :middle : symbol
237
237
  end
238
238
 
239
- def cast_boolean(value)
240
- ActiveModel::Type::Boolean.new.cast(value)
241
- end
242
-
243
239
  def normalize_string(value)
244
240
  return nil if value.nil?
245
241
 
@@ -79,8 +79,8 @@ module Hakumi
79
79
  }.compact
80
80
  },
81
81
  {
82
- id: @html_attrs[:wrapper_id],
83
- data: @html_attrs[:wrapper_data]
82
+ id: @html_attrs[:id],
83
+ data: @html_attrs[:data]
84
84
  }.compact
85
85
  )
86
86
  end
@@ -223,10 +223,6 @@ module Hakumi
223
223
 
224
224
  ((value.to_f - min) / (max - min) * 100).clamp(0, 100)
225
225
  end
226
-
227
- def cast_boolean(value)
228
- ActiveModel::Type::Boolean.new.cast(value)
229
- end
230
226
  end
231
227
  end
232
228
  end