odt-ui-rails 2.2.0 → 2.2.2

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.
@@ -0,0 +1,302 @@
1
+ module OdtUi
2
+ VERSION: String
3
+
4
+ module Helper
5
+ type button_variant = :filled | :frosted | :capsule | :ghost | :light | :outline | :outlined | :subtle | String
6
+ type button_color = :primary | :secondary | :surface | :muted | :inverse | :success | :warning | :danger | :info | :neutral | String
7
+ type button_size = :xs | :sm | :md | :lg | :xl | String
8
+ type radius_size = :none | :xs | :sm | :md | :lg | :xl | :"2xl" | :"3xl" | :"4xl" | :full | Symbol | String
9
+ type shadow_size = :none | :card | :dropdown | :modal | :popover | Symbol | String
10
+
11
+ type badge_variant = :subtle | :filled | :outlined | :outline | String
12
+ type badge_color = :primary | :secondary | :success | :warning | :danger | :info | :neutral | String
13
+ type badge_size = :sm | :md | String
14
+
15
+ type card_variant = :elevated | :outlined | :subtle | :muted | :ghost | :frosted | String
16
+ type card_background = :base | :surface | :surface_elevated | :surface_muted | :surface_subtle | :gradient_primary | :gradient_secondary | :gradient_vibrant | :gradient_hero | :frosted | :frosted_muted | :frosted_subtle | :frosted_gradient_primary | :frosted_gradient_secondary | :transparent | Symbol | String
17
+ type card_border = :none | :muted | :base | :strong | :primary | :secondary | :danger | :success | bool | Symbol | String
18
+ type card_padding = :none | :xs | :sm | :md | :lg | :xl | :"2xl" | Symbol | String
19
+ type card_tag = :div | :article | :section | :aside | :main | Symbol | String
20
+
21
+ type alert_variant = :success | :warning | :danger | :info | String
22
+ type heading_tag = :h1 | :h2 | :h3 | :h4 | :h5 | :h6 | String
23
+ type heading_size = :"5xl" | :"4xl" | :"3xl" | :"2xl" | :xl | :lg | Symbol | String
24
+ type font_weight = :light | :normal | :medium | :semibold | :bold | :extrabold | Symbol | String
25
+ type typography_color = :strong | :default | :muted | :subtle | :disabled | :primary | :secondary | :success | :warning | :danger | :info | Symbol | String
26
+
27
+ type text_tag = :p | :span | :div | :label | :small | Symbol | String
28
+ type text_size = :xs | :sm | :base | :lg | :xl | :"2xl" | Symbol | String
29
+
30
+ type avatar_size = :xs | :sm | :md | :lg | :xl | :"2xl" | String
31
+ type avatar_color = :secondary | :primary | :neutral | String
32
+
33
+ type input_variant = :outlined | :filled | :frosted | String
34
+ type input_size = :sm | :md | :lg | String
35
+ type input_resize = :none | :vertical | :horizontal | :both | String
36
+ type checkbox_color = :primary | :secondary | :success | :warning | :danger | :dark | :neutral | String
37
+ type checkbox_size = :sm | :md | :lg | String
38
+
39
+ # Renders an ODT Button component.
40
+ def odt_button: (
41
+ ?String? text,
42
+ ?variant: button_variant,
43
+ ?color: button_color,
44
+ ?size: button_size,
45
+ ?radius: radius_size?,
46
+ ?shadow: shadow_size?,
47
+ ?icon_only: bool,
48
+ ?full_width: bool,
49
+ ?loading: bool,
50
+ ?disabled: bool,
51
+ ?href: String?,
52
+ ?icon: String?,
53
+ ?right_icon: String?,
54
+ ?type: String,
55
+ **untyped
56
+ ) ?{ () -> untyped } -> untyped
57
+
58
+ # Renders an ODT Badge component.
59
+ def odt_badge: (
60
+ ?String? text,
61
+ ?variant: badge_variant,
62
+ ?color: badge_color,
63
+ ?size: badge_size,
64
+ ?radius: radius_size?,
65
+ ?dot: bool,
66
+ ?icon: String?,
67
+ **untyped
68
+ ) ?{ () -> untyped } -> untyped
69
+
70
+ # Renders an ODT Card component.
71
+ def odt_card: (
72
+ ?title: String?,
73
+ ?subtitle: String?,
74
+ ?variant: card_variant,
75
+ ?background: card_background?,
76
+ ?border: card_border?,
77
+ ?shadow: shadow_size?,
78
+ ?radius: radius_size?,
79
+ ?padding: card_padding?,
80
+ ?hoverable: bool,
81
+ ?hover: bool,
82
+ ?as: card_tag,
83
+ **untyped
84
+ ) ?{ () -> untyped } -> untyped
85
+
86
+ # Renders an ODT Alert banner.
87
+ def odt_alert: (
88
+ ?String? message,
89
+ ?variant: alert_variant,
90
+ ?icon: String?,
91
+ **untyped
92
+ ) ?{ () -> untyped } -> untyped
93
+
94
+ # Renders an ODT Heading element.
95
+ def odt_heading: (
96
+ ?String? text,
97
+ ?as: heading_tag,
98
+ ?size: heading_size?,
99
+ ?weight: font_weight?,
100
+ ?color: typography_color?,
101
+ ?truncate: bool,
102
+ **untyped
103
+ ) ?{ () -> untyped } -> untyped
104
+
105
+ # Renders styled body text.
106
+ def odt_text: (
107
+ ?String? text,
108
+ ?as: text_tag,
109
+ ?size: text_size?,
110
+ ?weight: font_weight?,
111
+ ?color: typography_color?,
112
+ ?truncate: bool,
113
+ **untyped
114
+ ) ?{ () -> untyped } -> untyped
115
+
116
+ # Renders an ODT Avatar element.
117
+ def odt_avatar: (
118
+ ?name: String?,
119
+ ?src: String?,
120
+ ?size: avatar_size,
121
+ ?color: avatar_color,
122
+ ?icon: String,
123
+ ?fallback: String?,
124
+ **untyped
125
+ ) -> untyped
126
+
127
+ # Renders a styled input field.
128
+ def odt_input: (
129
+ ?label: String?,
130
+ ?variant: input_variant,
131
+ ?size: input_size,
132
+ ?radius: radius_size?,
133
+ ?type: String,
134
+ ?placeholder: String?,
135
+ ?error: String?,
136
+ ?helper: String?,
137
+ ?helper_text: String?,
138
+ ?success: String?,
139
+ ?left_icon: String?,
140
+ ?right_icon: String?,
141
+ ?prefix: String?,
142
+ ?suffix: String?,
143
+ ?addon_before: String?,
144
+ ?addon_after: String?,
145
+ ?disabled: bool,
146
+ ?full_width: bool,
147
+ **untyped
148
+ ) -> untyped
149
+
150
+ # Renders a styled textarea field.
151
+ def odt_textarea: (
152
+ ?label: String?,
153
+ ?variant: input_variant,
154
+ ?size: input_size,
155
+ ?radius: radius_size?,
156
+ ?rows: Integer,
157
+ ?resize: input_resize,
158
+ ?error: String?,
159
+ ?helper: String?,
160
+ ?helper_text: String?,
161
+ ?success: String?,
162
+ ?disabled: bool,
163
+ ?full_width: bool,
164
+ **untyped
165
+ ) ?{ () -> untyped } -> untyped
166
+
167
+ # Renders a styled native <select> dropdown.
168
+ def odt_select: (
169
+ ?label: String?,
170
+ ?options: untyped,
171
+ ?variant: input_variant,
172
+ ?size: input_size,
173
+ ?radius: radius_size?,
174
+ ?prompt: String?,
175
+ ?error: String?,
176
+ ?helper: String?,
177
+ ?helper_text: String?,
178
+ ?success: String?,
179
+ ?disabled: bool,
180
+ ?full_width: bool,
181
+ **untyped
182
+ ) -> untyped
183
+
184
+ # Renders a styled checkbox.
185
+ def odt_checkbox: (
186
+ ?label: String?,
187
+ ?description: String?,
188
+ ?checked: bool,
189
+ ?color: checkbox_color,
190
+ ?size: checkbox_size,
191
+ ?radius: radius_size?,
192
+ ?disabled: bool,
193
+ ?error: String?,
194
+ **untyped
195
+ ) -> untyped
196
+
197
+ # Renders a styled radio button.
198
+ def odt_radio: (
199
+ ?label: String?,
200
+ ?description: String?,
201
+ ?checked: bool,
202
+ ?color: checkbox_color,
203
+ ?size: checkbox_size,
204
+ ?disabled: bool,
205
+ ?error: String?,
206
+ **untyped
207
+ ) -> untyped
208
+
209
+ # Renders a form field wrapper.
210
+ def odt_form_group: (
211
+ ?label: String?,
212
+ ?error: String?,
213
+ ?helper: String?,
214
+ ?helper_text: String?,
215
+ ?success: String?,
216
+ ?required: bool,
217
+ **untyped
218
+ ) ?{ () -> untyped } -> untyped
219
+
220
+ type toaster_position = :top_right | :top_center | :top_left | :bottom_right | :bottom_center | :bottom_left | Symbol | String
221
+ type toast_variant = :success | :warning | :danger | :error | :info | :loading | :frosted | Symbol | String
222
+
223
+ # Renders an ODT Toaster viewport container.
224
+ def odt_toaster: (
225
+ ?position: toaster_position,
226
+ ?id: String,
227
+ **untyped
228
+ ) ?{ () -> untyped } -> untyped
229
+
230
+ # Renders a single ODT Toast card.
231
+ def odt_toast: (
232
+ ?String? message,
233
+ ?title: String?,
234
+ ?variant: toast_variant,
235
+ ?icon: String?,
236
+ ?duration: Integer,
237
+ ?dismissible: bool,
238
+ ?radius: radius_size?,
239
+ **untyped
240
+ ) ?{ () -> untyped } -> untyped
241
+
242
+ # Renders active flash messages as ODT Toasts.
243
+ def odt_flash_toasts: (
244
+ ?untyped flash_hash,
245
+ ?duration: Integer
246
+ ) -> untyped
247
+
248
+ # Generates a Turbo Stream action for a toast.
249
+ def odt_toast_stream: (
250
+ ?String? message,
251
+ ?title: String?,
252
+ ?variant: toast_variant,
253
+ ?target: String,
254
+ ?action: Symbol | String,
255
+ ?duration: Integer,
256
+ **untyped
257
+ ) -> untyped
258
+
259
+ type modal_size = :sm | :md | :lg | :xl | :full | Symbol | String
260
+
261
+ # Renders an ODT Modal dialog container.
262
+ def odt_modal: (
263
+ ?id: String?,
264
+ ?title: String?,
265
+ ?subtitle: String?,
266
+ ?size: modal_size,
267
+ ?radius: radius_size?,
268
+ ?dismissible: bool,
269
+ ?open: bool,
270
+ ?prevent_backdrop_close: bool,
271
+ **untyped
272
+ ) ?{ () -> untyped } -> untyped
273
+
274
+ # Renders an ODT Modal Header subcomponent.
275
+ def odt_modal_header: (
276
+ ?title: String?,
277
+ ?subtitle: String?,
278
+ ?dismissible: bool,
279
+ **untyped
280
+ ) ?{ () -> untyped } -> untyped
281
+
282
+ # Renders an ODT Modal Body subcomponent.
283
+ def odt_modal_body: (
284
+ **untyped
285
+ ) ?{ () -> untyped } -> untyped
286
+
287
+ # Renders an ODT Modal Footer subcomponent.
288
+ def odt_modal_footer: (
289
+ **untyped
290
+ ) ?{ () -> untyped } -> untyped
291
+ end
292
+ end
293
+
294
+ module ActionView
295
+ class Base
296
+ include OdtUi::Helper
297
+ end
298
+
299
+ module Helpers
300
+ include OdtUi::Helper
301
+ end
302
+ end
data/lib/odt_ui/helper.rb CHANGED
@@ -677,6 +677,271 @@ module OdtUi
677
677
  end
678
678
  end
679
679
 
680
+ # Renders an ODT Toaster viewport container.
681
+ #
682
+ # @param position [:top_right, :top_center, :top_left, :bottom_right, :bottom_center, :bottom_left]
683
+ # @param id [String] Element ID for Turbo Stream targeting (default: "odt-toasts")
684
+ # @return [ActiveSupport::SafeBuffer]
685
+ def odt_toaster(position: :top_right, id: "odt-toasts", **html_options, &block)
686
+ pos_key = position.to_s.tr("_", "-")
687
+ classes = [
688
+ "odt-toaster",
689
+ "odt-toaster--#{pos_key}",
690
+ html_options.delete(:class)
691
+ ]
692
+
693
+ opts = html_options.merge(
694
+ id: id,
695
+ class: classes.compact.reject(&:blank?).join(" "),
696
+ role: "region",
697
+ aria: { live: "polite" }
698
+ )
699
+
700
+ inner_content = block_given? ? capture(&block) : nil
701
+ tag.div(inner_content, **opts)
702
+ end
703
+
704
+ # Renders a single ODT Toast card with Stimulus controller.
705
+ #
706
+ # @param message [String, nil]
707
+ # @param title [String, nil]
708
+ # @param variant [:success, :warning, :danger, :error, :info, :loading, :frosted]
709
+ # @param icon [String, nil]
710
+ # @param duration [Integer] Auto-dismiss duration in milliseconds (0 to disable)
711
+ # @param dismissible [Boolean] Whether to display close button
712
+ # @param radius [:none, :xs, :sm, :md, :lg, :xl, :"2xl", :"3xl", :"4xl", :full, nil]
713
+ # @return [ActiveSupport::SafeBuffer]
714
+ def odt_toast(message = nil, title: nil, variant: :success, icon: nil, duration: 4000, dismissible: true, radius: nil, **html_options, &block)
715
+ variant_key = variant.to_sym == :error ? :danger : variant.to_sym
716
+ default_icons = {
717
+ success: "fa-solid fa-circle-check",
718
+ warning: "fa-solid fa-triangle-exclamation",
719
+ danger: "fa-solid fa-circle-xmark",
720
+ info: "fa-solid fa-circle-info",
721
+ loading: "fa-solid fa-spinner"
722
+ }
723
+
724
+ icon_name = icon || default_icons[variant_key] || default_icons[:info]
725
+
726
+ classes = [
727
+ "odt-toast",
728
+ "odt-toast--#{variant_key.to_s.tr('_', '-')}"
729
+ ]
730
+ classes << "odt-radius-#{radius.to_s.tr('_', '-')}" if radius.present?
731
+ classes << html_options.delete(:class)
732
+
733
+ data_attrs = {
734
+ controller: "odt-toast",
735
+ odt_toast_duration_value: duration,
736
+ action: "mouseenter->odt-toast#pauseTimer mouseleave->odt-toast#resumeTimer"
737
+ }.merge(html_options.delete(:data) || {})
738
+
739
+ opts = html_options.merge(
740
+ class: classes.compact.reject(&:blank?).join(" "),
741
+ role: "status",
742
+ data: data_attrs
743
+ )
744
+
745
+ parts = []
746
+ if icon_name.present?
747
+ icon_classes = ["odt-toast__icon", "odt-toast__icon--#{variant_key}"]
748
+ parts << tag.span(render_icon_element(icon_name), class: icon_classes.join(" "))
749
+ end
750
+
751
+ body_content = block_given? ? capture(&block) : message
752
+
753
+ parts << tag.div(class: "odt-toast__content") do
754
+ c_parts = []
755
+ c_parts << tag.p(title, class: "odt-toast__title") if title.present?
756
+ c_parts << tag.p(body_content, class: "odt-toast__message") if body_content.present?
757
+ safe_join(c_parts)
758
+ end
759
+
760
+ if dismissible
761
+ parts << tag.button(
762
+ "×".html_safe,
763
+ type: "button",
764
+ class: "odt-toast__close",
765
+ aria: { label: "Close" },
766
+ data: { action: "click->odt-toast#dismiss" }
767
+ )
768
+ end
769
+
770
+ inner_content = safe_join(parts.compact)
771
+ tag.div(inner_content, **opts)
772
+ end
773
+
774
+ # Renders all active flash messages as ODT Toasts.
775
+ #
776
+ # @param flash_hash [ActionDispatch::Flash::FlashHash, Hash] Flash messages hash (default: flash)
777
+ # @param duration [Integer] Auto-dismiss duration in milliseconds
778
+ # @return [ActiveSupport::SafeBuffer]
779
+ def odt_flash_toasts(flash_hash = flash, duration: 4000)
780
+ return "".html_safe if flash_hash.blank?
781
+
782
+ toasts = []
783
+ flash_hash.each do |type, message|
784
+ next if message.blank?
785
+
786
+ variant = case type.to_sym
787
+ when :notice, :success
788
+ :success
789
+ when :alert, :error, :danger
790
+ :danger
791
+ when :warning
792
+ :warning
793
+ else
794
+ :info
795
+ end
796
+
797
+ toasts << odt_toast(message, variant: variant, duration: duration)
798
+ end
799
+
800
+ safe_join(toasts)
801
+ end
802
+
803
+ # Generates a Turbo Stream action to render a toast asynchronously.
804
+ #
805
+ # @param message [String, nil]
806
+ # @param title [String, nil]
807
+ # @param variant [:success, :warning, :danger, :error, :info]
808
+ # @param target [String] Target container ID (default: "odt-toasts")
809
+ # @param action [:append, :prepend] Turbo stream action (default: :append)
810
+ # @param duration [Integer] Auto-dismiss duration in ms (default: 4000)
811
+ # @return [ActiveSupport::SafeBuffer]
812
+ def odt_toast_stream(message = nil, title: nil, variant: :success, target: "odt-toasts", action: :append, duration: 4000, **options)
813
+ toast_html = odt_toast(message, title: title, variant: variant, duration: duration, **options)
814
+
815
+ if respond_to?(:turbo_stream)
816
+ turbo_stream.public_send(action, target, toast_html)
817
+ else
818
+ tag.public_send("turbo-stream", action: action, target: target) do
819
+ tag.template(toast_html)
820
+ end
821
+ end
822
+ end
823
+
824
+ # Renders an ODT Modal dialog container with Stimulus controller.
825
+ #
826
+ # @param id [String, nil] Unique HTML ID of the modal
827
+ # @param title [String, nil] Header title text
828
+ # @param subtitle [String, nil] Header subtitle text
829
+ # @param size [:sm, :md, :lg, :xl, :full] Dialog width size (default: :md)
830
+ # @param radius [:none, :xs, :sm, :md, :lg, :xl, :"2xl", :"3xl", :"4xl", :full, nil]
831
+ # @param dismissible [Boolean] Whether to render the header close button (default: true)
832
+ # @param open [Boolean] Whether modal is initially open (default: false)
833
+ # @param prevent_backdrop_close [Boolean] Prevent closing when clicking overlay (default: false)
834
+ # @return [ActiveSupport::SafeBuffer]
835
+ def odt_modal(id: nil, title: nil, subtitle: nil, size: :md, radius: :"2xl", dismissible: true, open: false, prevent_backdrop_close: false, **html_options, &block)
836
+ size_key = size.to_s.tr("_", "-")
837
+ radius_key = radius.to_s.tr("_", "-")
838
+
839
+ overlay_classes = [
840
+ "odt-modal-overlay",
841
+ ("hidden" unless open),
842
+ html_options.delete(:class)
843
+ ]
844
+
845
+ data_attrs = {
846
+ controller: "odt-modal",
847
+ odt_modal_open_value: open,
848
+ odt_modal_prevent_backdrop_close_value: prevent_backdrop_close,
849
+ action: "click->odt-modal#backdropClose keydown.esc@window->odt-modal#close"
850
+ }.merge(html_options.delete(:data) || {})
851
+
852
+ opts = html_options.merge(
853
+ id: id,
854
+ class: overlay_classes.compact.reject(&:blank?).join(" "),
855
+ role: "dialog",
856
+ aria: { modal: "true", hidden: (!open).to_s },
857
+ data: data_attrs
858
+ )
859
+
860
+ modal_classes = [
861
+ "odt-modal",
862
+ "odt-modal--#{size_key}",
863
+ "odt-radius-#{radius_key}"
864
+ ]
865
+
866
+ body_content = block_given? ? capture(&block) : nil
867
+
868
+ tag.div(**opts) do
869
+ tag.div(class: modal_classes.join(" "), data: { odt_modal_target: "dialog" }) do
870
+ parts = []
871
+ if title.present? || subtitle.present? || dismissible
872
+ parts << odt_modal_header(title: title, subtitle: subtitle, dismissible: dismissible)
873
+ end
874
+
875
+ if body_content.present?
876
+ if body_content.include?("odt-modal__body") || body_content.include?("odt-modal__header")
877
+ parts << body_content
878
+ else
879
+ parts << tag.div(body_content, class: "odt-modal__body")
880
+ end
881
+ end
882
+
883
+ safe_join(parts)
884
+ end
885
+ end
886
+ end
887
+
888
+ # Renders an ODT Modal Header subcomponent.
889
+ #
890
+ # @param title [String, nil]
891
+ # @param subtitle [String, nil]
892
+ # @param dismissible [Boolean]
893
+ # @return [ActiveSupport::SafeBuffer]
894
+ def odt_modal_header(title: nil, subtitle: nil, dismissible: true, **html_options, &block)
895
+ classes = ["odt-modal__header", html_options.delete(:class)]
896
+ opts = html_options.merge(class: classes.compact.reject(&:blank?).join(" "))
897
+
898
+ tag.div(**opts) do
899
+ parts = []
900
+ if block_given?
901
+ parts << capture(&block)
902
+ else
903
+ parts << tag.div(class: "odt-modal__header-content") do
904
+ c_parts = []
905
+ c_parts << tag.h3(title, class: "odt-modal__title") if title.present?
906
+ c_parts << tag.p(subtitle, class: "odt-modal__subtitle") if subtitle.present?
907
+ safe_join(c_parts)
908
+ end
909
+ end
910
+
911
+ if dismissible
912
+ parts << tag.button(
913
+ "×".html_safe,
914
+ type: "button",
915
+ class: "odt-modal__close",
916
+ aria: { label: "Close" },
917
+ data: { action: "click->odt-modal#close" }
918
+ )
919
+ end
920
+
921
+ safe_join(parts)
922
+ end
923
+ end
924
+
925
+ # Renders an ODT Modal Body subcomponent.
926
+ #
927
+ # @return [ActiveSupport::SafeBuffer]
928
+ def odt_modal_body(**html_options, &block)
929
+ classes = ["odt-modal__body", html_options.delete(:class)]
930
+ opts = html_options.merge(class: classes.compact.reject(&:blank?).join(" "))
931
+ content = block_given? ? capture(&block) : nil
932
+ tag.div(content, **opts)
933
+ end
934
+
935
+ # Renders an ODT Modal Footer subcomponent.
936
+ #
937
+ # @return [ActiveSupport::SafeBuffer]
938
+ def odt_modal_footer(**html_options, &block)
939
+ classes = ["odt-modal__footer", html_options.delete(:class)]
940
+ opts = html_options.merge(class: classes.compact.reject(&:blank?).join(" "))
941
+ content = block_given? ? capture(&block) : nil
942
+ tag.div(content, **opts)
943
+ end
944
+
680
945
  private
681
946
 
682
947
  # Normalizes button variant key with backwards compatibility
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OdtUi
4
- VERSION = "2.2.0"
4
+ VERSION = "2.2.2"
5
5
  end
data/sig/odt_ui.rbs CHANGED
@@ -216,6 +216,78 @@ module OdtUi
216
216
  ?required: bool,
217
217
  **untyped
218
218
  ) ?{ () -> untyped } -> untyped
219
+
220
+ type toaster_position = :top_right | :top_center | :top_left | :bottom_right | :bottom_center | :bottom_left | Symbol | String
221
+ type toast_variant = :success | :warning | :danger | :error | :info | :loading | :frosted | Symbol | String
222
+
223
+ # Renders an ODT Toaster viewport container.
224
+ def odt_toaster: (
225
+ ?position: toaster_position,
226
+ ?id: String,
227
+ **untyped
228
+ ) ?{ () -> untyped } -> untyped
229
+
230
+ # Renders a single ODT Toast card.
231
+ def odt_toast: (
232
+ ?String? message,
233
+ ?title: String?,
234
+ ?variant: toast_variant,
235
+ ?icon: String?,
236
+ ?duration: Integer,
237
+ ?dismissible: bool,
238
+ ?radius: radius_size?,
239
+ **untyped
240
+ ) ?{ () -> untyped } -> untyped
241
+
242
+ # Renders active flash messages as ODT Toasts.
243
+ def odt_flash_toasts: (
244
+ ?untyped flash_hash,
245
+ ?duration: Integer
246
+ ) -> untyped
247
+
248
+ # Generates a Turbo Stream action for a toast.
249
+ def odt_toast_stream: (
250
+ ?String? message,
251
+ ?title: String?,
252
+ ?variant: toast_variant,
253
+ ?target: String,
254
+ ?action: Symbol | String,
255
+ ?duration: Integer,
256
+ **untyped
257
+ ) -> untyped
258
+
259
+ type modal_size = :sm | :md | :lg | :xl | :full | Symbol | String
260
+
261
+ # Renders an ODT Modal dialog container.
262
+ def odt_modal: (
263
+ ?id: String?,
264
+ ?title: String?,
265
+ ?subtitle: String?,
266
+ ?size: modal_size,
267
+ ?radius: radius_size?,
268
+ ?dismissible: bool,
269
+ ?open: bool,
270
+ ?prevent_backdrop_close: bool,
271
+ **untyped
272
+ ) ?{ () -> untyped } -> untyped
273
+
274
+ # Renders an ODT Modal Header subcomponent.
275
+ def odt_modal_header: (
276
+ ?title: String?,
277
+ ?subtitle: String?,
278
+ ?dismissible: bool,
279
+ **untyped
280
+ ) ?{ () -> untyped } -> untyped
281
+
282
+ # Renders an ODT Modal Body subcomponent.
283
+ def odt_modal_body: (
284
+ **untyped
285
+ ) ?{ () -> untyped } -> untyped
286
+
287
+ # Renders an ODT Modal Footer subcomponent.
288
+ def odt_modal_footer: (
289
+ **untyped
290
+ ) ?{ () -> untyped } -> untyped
219
291
  end
220
292
  end
221
293