okonomi_ui_kit 0.1.8 → 0.1.10
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/README.md +50 -6
- data/app/assets/builds/okonomi_ui_kit/application.tailwind.css +508 -225
- data/app/helpers/okonomi_ui_kit/CLAUDE.md +619 -0
- data/app/helpers/okonomi_ui_kit/application_helper.rb +8 -0
- data/app/helpers/okonomi_ui_kit/attribute_section_helper.rb +5 -5
- data/app/helpers/okonomi_ui_kit/component.rb +14 -6
- data/app/helpers/okonomi_ui_kit/components/alert.rb +1 -1
- data/app/helpers/okonomi_ui_kit/components/badge.rb +4 -4
- data/app/helpers/okonomi_ui_kit/components/breadcrumbs.rb +4 -4
- data/app/helpers/okonomi_ui_kit/components/button_base.rb +94 -22
- data/app/helpers/okonomi_ui_kit/components/button_tag.rb +14 -8
- data/app/helpers/okonomi_ui_kit/components/button_to.rb +8 -7
- data/app/helpers/okonomi_ui_kit/components/code.rb +41 -37
- data/app/helpers/okonomi_ui_kit/components/confirmation_modal.rb +130 -0
- data/app/helpers/okonomi_ui_kit/components/dropdown_button.rb +147 -0
- data/app/helpers/okonomi_ui_kit/components/forms/check_box_with_label.rb +38 -0
- data/app/helpers/okonomi_ui_kit/components/forms/collection_select.rb +57 -0
- data/app/helpers/okonomi_ui_kit/components/forms/date_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/datetime_local_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/email_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/field.rb +24 -0
- data/app/helpers/okonomi_ui_kit/components/forms/field_set.rb +17 -0
- data/app/helpers/okonomi_ui_kit/components/forms/input_base.rb +57 -0
- data/app/helpers/okonomi_ui_kit/components/forms/label.rb +27 -0
- data/app/helpers/okonomi_ui_kit/components/forms/multi_select.rb +18 -0
- data/app/helpers/okonomi_ui_kit/components/forms/number_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/password_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/search_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/select.rb +57 -0
- data/app/helpers/okonomi_ui_kit/components/forms/show_if.rb +28 -0
- data/app/helpers/okonomi_ui_kit/components/forms/telephone_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/text_area.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/text_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/time_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms/upload_field.rb +25 -0
- data/app/helpers/okonomi_ui_kit/components/forms/url_field.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/forms.rb +6 -0
- data/app/helpers/okonomi_ui_kit/components/icon.rb +6 -6
- data/app/helpers/okonomi_ui_kit/components/link_to.rb +11 -10
- data/app/helpers/okonomi_ui_kit/components/navigation.rb +98 -0
- data/app/helpers/okonomi_ui_kit/components/page.rb +18 -203
- data/app/helpers/okonomi_ui_kit/components/page_header.rb +111 -0
- data/app/helpers/okonomi_ui_kit/components/page_section.rb +145 -0
- data/app/helpers/okonomi_ui_kit/components/table.rb +7 -8
- data/app/helpers/okonomi_ui_kit/components/typography.rb +16 -16
- data/app/helpers/okonomi_ui_kit/components.rb +4 -0
- data/app/helpers/okonomi_ui_kit/configs.rb +4 -0
- data/app/helpers/okonomi_ui_kit/form_builder.rb +39 -130
- data/app/helpers/okonomi_ui_kit/form_component.rb +7 -0
- data/app/helpers/okonomi_ui_kit/svg_icons.rb +5 -5
- data/app/helpers/okonomi_ui_kit/t_w_merge.rb +33 -27
- data/app/helpers/okonomi_ui_kit/ui_helper.rb +17 -58
- data/app/javascript/okonomi_ui_kit/controllers/dropdown_controller.js +6 -0
- data/app/views/okonomi/components/confirmation_modal/_confirmation_modal.html.erb +76 -0
- data/app/views/okonomi/components/dropdown_button/_dropdown_button.html.erb +282 -0
- data/app/views/okonomi/components/forms/check_box_with_label/_check_box_with_label.html.erb +6 -0
- data/app/views/okonomi/{forms/tailwind → components/forms/field}/_field.html.erb +7 -7
- data/app/views/okonomi/components/forms/field_set/_field_set.html.erb +3 -0
- data/app/views/okonomi/components/forms/upload_field/_upload_field.html.erb +1 -0
- data/app/views/okonomi/components/navigation/_link.html.erb +18 -0
- data/app/views/okonomi/components/navigation/_navigation.html.erb +4 -0
- data/app/views/okonomi/components/page/_page.html.erb +1 -1
- data/app/views/okonomi/components/page_header/_page_header.html.erb +4 -0
- data/app/views/okonomi/components/page_section/_page_section.html.erb +4 -0
- data/app/views/okonomi/forms/tailwind/_checkbox_label.html.erb +2 -2
- data/app/views/okonomi/forms/tailwind/_multi_select.html.erb +2 -4
- data/app/views/okonomi/forms/tailwind/_upload_field.html.erb +10 -10
- data/config/importmap.rb +1 -1
- data/lib/okonomi_ui_kit/engine.rb +0 -1
- data/lib/okonomi_ui_kit/version.rb +1 -1
- metadata +47 -16
- data/app/helpers/okonomi_ui_kit/navigation_helper.rb +0 -72
- data/app/helpers/okonomi_ui_kit/theme.rb +0 -136
- data/app/helpers/okonomi_ui_kit/theme_helper.rb +0 -17
- data/app/views/okonomi/forms/tailwind/_field_set.html.erb +0 -3
- data/app/views/okonomi/modals/_confirmation_modal.html.erb +0 -77
- data/app/views/okonomi/navigation/_link.html.erb +0 -15
- data/app/views/okonomi/navigation/_menu.html.erb +0 -3
- data/app/views/okonomi/navigation/_navbar.html.erb +0 -105
- data/app/views/okonomi/page_builder/_page.html.erb +0 -3
@@ -7,202 +7,111 @@ module OkonomiUiKit
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def field_set(options = {}, &block)
|
10
|
-
|
10
|
+
ui.forms.field_set(self, options, &block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def field(field_id = nil, options = {}, &block)
|
14
|
-
|
14
|
+
ui.forms.field(self, field_id, options, &block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def upload_field(method, options = {})
|
18
|
-
|
18
|
+
ui.forms.upload_field(self, method, options)
|
19
19
|
end
|
20
20
|
|
21
21
|
def text_field(method, options = {})
|
22
|
-
|
23
|
-
super(method, { autocomplete: "off" }.merge(options).merge(class: css))
|
22
|
+
super(*resolve_arguments(:text_field, method, options))
|
24
23
|
end
|
25
24
|
|
26
25
|
def email_field(method, options = {})
|
27
|
-
|
28
|
-
super(method, options.merge(class: css))
|
26
|
+
super(*resolve_arguments(:email_field, method, options))
|
29
27
|
end
|
30
28
|
|
31
29
|
def url_field(method, options = {})
|
32
|
-
|
33
|
-
|
30
|
+
super(*resolve_arguments(:url_field, method, options))
|
31
|
+
end
|
32
|
+
|
33
|
+
def resolve_arguments(component_name, *args)
|
34
|
+
component = ui.forms.resolve_component(component_name)
|
35
|
+
|
36
|
+
if component.nil?
|
37
|
+
args
|
38
|
+
else
|
39
|
+
component.render_arguments(object, *args)
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
def password_field(method, options = {})
|
37
|
-
|
38
|
-
super(method, options.merge(class: css))
|
44
|
+
super(*resolve_arguments(:password_field, method, options))
|
39
45
|
end
|
40
46
|
|
41
47
|
def number_field(method, options = {})
|
42
|
-
|
43
|
-
super(method, options.merge(class: css))
|
48
|
+
super(*resolve_arguments(:number_field, method, options))
|
44
49
|
end
|
45
50
|
|
46
51
|
def telephone_field(method, options = {})
|
47
|
-
|
48
|
-
super(method, options.merge(class: css))
|
52
|
+
super(*resolve_arguments(:telephone_field, method, options))
|
49
53
|
end
|
50
54
|
|
51
55
|
def search_field(method, options = {})
|
52
|
-
|
53
|
-
super(method, options.merge(class: css))
|
56
|
+
super(*resolve_arguments(:search_field, method, options))
|
54
57
|
end
|
55
58
|
|
56
59
|
def date_field(method, options = {})
|
57
|
-
|
58
|
-
super(method, options.merge(class: css))
|
60
|
+
super(*resolve_arguments(:date_field, method, options))
|
59
61
|
end
|
60
62
|
|
61
63
|
def datetime_local_field(method, options = {})
|
62
|
-
|
63
|
-
super(method, options.merge(class: css))
|
64
|
+
super(*resolve_arguments(:datetime_local_field, method, options))
|
64
65
|
end
|
65
66
|
|
66
67
|
def time_field(method, options = {})
|
67
|
-
|
68
|
-
super(method, options.merge(class: css))
|
68
|
+
super(*resolve_arguments(:time_field, method, options))
|
69
69
|
end
|
70
70
|
|
71
71
|
def text_area(method, options = {})
|
72
|
-
|
73
|
-
super(method, options.merge(class: css))
|
72
|
+
super(*resolve_arguments(:text_area, method, options))
|
74
73
|
end
|
75
74
|
|
76
75
|
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
77
|
-
|
78
|
-
ui.get_theme.dig(:components, :select, :root),
|
79
|
-
when_errors(
|
80
|
-
method,
|
81
|
-
ui.get_theme.dig(:components, :select, :error),
|
82
|
-
ui.get_theme.dig(:components, :select, :valid)
|
83
|
-
),
|
84
|
-
html_options[:class]
|
85
|
-
].compact.join(' ').split(' ').uniq
|
86
|
-
|
87
|
-
select_html = super(method, choices, options, html_options.merge(class: css), &block)
|
88
|
-
icon_html = @template.ui.icon(
|
89
|
-
ui.get_theme.dig(:components, :select, :icon, :file),
|
90
|
-
class: ui.get_theme.dig(:components, :select, :icon, :class)
|
91
|
-
)
|
92
|
-
|
93
|
-
@template.content_tag(:div, class: ui.get_theme.dig(:components, :select, :wrapper)) do
|
94
|
-
@template.concat(select_html)
|
95
|
-
@template.concat(icon_html)
|
96
|
-
end
|
76
|
+
ui.forms.select(self, method, choices, options, html_options, &block)
|
97
77
|
end
|
98
78
|
|
99
79
|
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
100
|
-
|
101
|
-
ui.get_theme.dig(:components, :select, :root),
|
102
|
-
when_errors(
|
103
|
-
method,
|
104
|
-
ui.get_theme.dig(:components, :select, :error),
|
105
|
-
ui.get_theme.dig(:components, :select, :valid)
|
106
|
-
),
|
107
|
-
html_options[:class]
|
108
|
-
].compact.join(' ').split(' ').uniq
|
109
|
-
|
110
|
-
select_html = super(method, collection, value_method, text_method, options, html_options.merge(class: css))
|
111
|
-
icon_html = @template.ui.icon(
|
112
|
-
ui.get_theme.dig(:components, :select, :icon, :file),
|
113
|
-
class: ui.get_theme.dig(:components, :select, :icon, :class)
|
114
|
-
)
|
115
|
-
|
116
|
-
@template.content_tag(:div, class: ui.get_theme.dig(:components, :select, :wrapper)) do
|
117
|
-
@template.concat(select_html)
|
118
|
-
@template.concat(icon_html)
|
119
|
-
end
|
80
|
+
ui.forms.collection_select(self, method, collection, value_method, text_method, options, html_options)
|
120
81
|
end
|
121
82
|
|
122
83
|
def multi_select(method, **options)
|
123
|
-
|
124
|
-
partial: 'okonomi/forms/tailwind/multi_select',
|
125
|
-
locals: {
|
126
|
-
form: self,
|
127
|
-
method: method,
|
128
|
-
options: options
|
129
|
-
}
|
130
|
-
)
|
84
|
+
ui.forms.multi_select(self, method, options)
|
131
85
|
end
|
132
86
|
|
133
87
|
def label(method, text = nil, options = {}, &block)
|
134
|
-
|
135
|
-
super(method, text, merge_class(options, base_classes), &block)
|
88
|
+
ui.forms.label(self, method, text, options, &block)
|
136
89
|
end
|
137
90
|
|
138
91
|
def submit(value = nil, options = {})
|
139
|
-
|
140
|
-
|
92
|
+
value, options = nil, value if value.is_a?(Hash)
|
93
|
+
value ||= submit_default_value
|
141
94
|
|
142
|
-
|
143
|
-
|
95
|
+
options ||= {}
|
96
|
+
options[:type] = "submit"
|
97
|
+
options[:variant] ||= "contained"
|
98
|
+
options[:color] ||= "primary"
|
99
|
+
|
100
|
+
ui.button_tag(value, options)
|
144
101
|
end
|
145
102
|
|
146
103
|
def check_box_with_label(method, options = {}, checked_value = true, unchecked_value = false)
|
147
|
-
|
148
|
-
@template.concat check_box(
|
149
|
-
method,
|
150
|
-
{
|
151
|
-
class: ui.get_theme.dig(:components, :checkbox, :input, :root)
|
152
|
-
}.merge(options || {}),
|
153
|
-
checked_value,
|
154
|
-
unchecked_value
|
155
|
-
)
|
156
|
-
@template.concat @template.render('okonomi/forms/tailwind/checkbox_label', method:, options:, form: self)
|
157
|
-
end
|
104
|
+
ui.forms.check_box_with_label(self, method, options, checked_value, unchecked_value)
|
158
105
|
end
|
159
106
|
|
160
107
|
def show_if(field:, equals:, &block)
|
161
|
-
|
162
|
-
@template.tag.div(
|
163
|
-
class: "hidden",
|
164
|
-
data: {
|
165
|
-
controller: "form-field-visibility",
|
166
|
-
"form-field-visibility-field-id-value": field_id,
|
167
|
-
"form-field-visibility-equals-value": equals
|
168
|
-
},
|
169
|
-
&block
|
170
|
-
)
|
108
|
+
ui.forms.show_if(self, field: field, equals: equals, &block)
|
171
109
|
end
|
172
110
|
|
173
111
|
private
|
174
112
|
|
175
|
-
def input_field_classes(method, type, options, include_disabled: true)
|
176
|
-
css_classes = [
|
177
|
-
ui.get_theme.dig(:components, :input, :types, type, :root) || ui.get_theme.dig(:components, :input, :types, :text, :root),
|
178
|
-
when_errors(
|
179
|
-
method,
|
180
|
-
ui.get_theme.dig(:components, :input, :types, type, :error) || ui.get_theme.dig(:components, :input, :types, :text, :error),
|
181
|
-
ui.get_theme.dig(:components, :input, :types, type, :valid) || ui.get_theme.dig(:components, :input, :types, :text, :valid)
|
182
|
-
),
|
183
|
-
options[:class]
|
184
|
-
]
|
185
|
-
|
186
|
-
if include_disabled
|
187
|
-
css_classes << (
|
188
|
-
ui.get_theme.dig(:components, :input, :types, type, :disabled) || ui.get_theme.dig(:components, :input, :types, :text, :disabled)
|
189
|
-
)
|
190
|
-
end
|
191
|
-
|
192
|
-
css_classes.compact.join(' ').split(' ').uniq
|
193
|
-
end
|
194
|
-
|
195
|
-
def when_errors(method, value, default_value = nil)
|
196
|
-
key = method.to_s.gsub('_id', '').to_sym
|
197
|
-
if object.errors.include?(key) || object.errors.include?(method)
|
198
|
-
value
|
199
|
-
else
|
200
|
-
default_value
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
113
|
def merge_class(options, new_class)
|
205
|
-
options[:class] =
|
114
|
+
options[:class] = OkonomiUiKit::TWMerge.merge(options[:class] || "", new_class)
|
206
115
|
options
|
207
116
|
end
|
208
117
|
end
|
@@ -13,16 +13,16 @@ module OkonomiUiKit
|
|
13
13
|
|
14
14
|
def self.file_path(name)
|
15
15
|
# First check in the host application
|
16
|
-
host_path = Rails.root.join(
|
16
|
+
host_path = Rails.root.join("app", "assets", "images", "#{name}.svg")
|
17
17
|
return host_path if File.exist?(host_path)
|
18
|
-
|
18
|
+
|
19
19
|
# Fall back to the engine's icons
|
20
|
-
engine_path = OkonomiUiKit::Engine.root.join(
|
20
|
+
engine_path = OkonomiUiKit::Engine.root.join("app", "assets", "images", "#{name}.svg")
|
21
21
|
return engine_path if File.exist?(engine_path)
|
22
|
-
|
22
|
+
|
23
23
|
nil
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Deprecated, kept for backwards compatibility
|
27
27
|
def self.file_name(name)
|
28
28
|
file_path(name)
|
@@ -11,7 +11,7 @@ module OkonomiUiKit
|
|
11
11
|
tokens.each do |tok|
|
12
12
|
variants, base = split_variants(tok)
|
13
13
|
group = conflict_group_for(base)
|
14
|
-
key = [variants, group || "literal:#{base}"]
|
14
|
+
key = [ variants, group || "literal:#{base}" ]
|
15
15
|
|
16
16
|
if index_by_key.key?(key)
|
17
17
|
pos = index_by_key[key]
|
@@ -22,7 +22,13 @@ module OkonomiUiKit
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
result.join(
|
25
|
+
result.join(" ")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.merge_all(*args)
|
29
|
+
args.compact.reduce do |merged, arg|
|
30
|
+
merge(merged, arg)
|
31
|
+
end
|
26
32
|
end
|
27
33
|
|
28
34
|
# Deep-merge two hashes; when both values are strings, merge as Tailwind classes.
|
@@ -54,39 +60,39 @@ module OkonomiUiKit
|
|
54
60
|
# Conflict groups (minimal, extensible). More specific patterns first.
|
55
61
|
CONFLICT_RULES = [
|
56
62
|
# Typography
|
57
|
-
[/^text-(?:xs|sm|base|lg|xl|\d+xl|\[\S+\])$/, :text_size],
|
58
|
-
[/^text-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :text_color],
|
59
|
-
[/^font-(?:thin|extralight|light|normal|medium|semibold|bold|extrabold|black)$/, :font_weight],
|
60
|
-
[/^leading-(?:none|tight|snug|normal|relaxed|loose|\d+|\[.+\])$/, :line_height],
|
61
|
-
[/^tracking-(?:tighter|tight|normal|wide|widest|\[.+\])$/, :letter_spacing],
|
63
|
+
[ /^text-(?:xs|sm|base|lg|xl|\d+xl|\[\S+\])$/, :text_size ],
|
64
|
+
[ /^text-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :text_color ],
|
65
|
+
[ /^font-(?:thin|extralight|light|normal|medium|semibold|bold|extrabold|black)$/, :font_weight ],
|
66
|
+
[ /^leading-(?:none|tight|snug|normal|relaxed|loose|\d+|\[.+\])$/, :line_height ],
|
67
|
+
[ /^tracking-(?:tighter|tight|normal|wide|widest|\[.+\])$/, :letter_spacing ],
|
62
68
|
|
63
69
|
# Display & position
|
64
|
-
[/^(?:hidden|block|inline|inline-block|flex|inline-flex|grid|inline-grid|table|inline-table|flow-root)$/, :display],
|
65
|
-
[/^(?:static|fixed|absolute|relative|sticky)$/, :position],
|
70
|
+
[ /^(?:hidden|block|inline|inline-block|flex|inline-flex|grid|inline-grid|table|inline-table|flow-root)$/, :display ],
|
71
|
+
[ /^(?:static|fixed|absolute|relative|sticky)$/, :position ],
|
66
72
|
|
67
73
|
# Flexbox
|
68
|
-
[/^flex-(?:row|col|row-reverse|col-reverse)$/, :flex_direction],
|
69
|
-
[/^flex-(?:wrap|nowrap|wrap-reverse)$/, :flex_wrap],
|
70
|
-
[/^items-(?:start|end|center|baseline|stretch)$/, :align_items],
|
71
|
-
[/^justify-(?:start|end|center|between|around|evenly)$/, :justify_content],
|
74
|
+
[ /^flex-(?:row|col|row-reverse|col-reverse)$/, :flex_direction ],
|
75
|
+
[ /^flex-(?:wrap|nowrap|wrap-reverse)$/, :flex_wrap ],
|
76
|
+
[ /^items-(?:start|end|center|baseline|stretch)$/, :align_items ],
|
77
|
+
[ /^justify-(?:start|end|center|between|around|evenly)$/, :justify_content ],
|
72
78
|
|
73
79
|
# Borders
|
74
|
-
[/^(?:border|border-(?:\d+|\[\S+\]))$/, :border_width_overall],
|
75
|
-
[/^border-[trblxy](?:-\d+|\[\S+\])?$/, :border_width_side],
|
76
|
-
[/^border-(?:solid|dashed|dotted|double|none)$/, :border_style],
|
77
|
-
[/^border-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :border_color],
|
80
|
+
[ /^(?:border|border-(?:\d+|\[\S+\]))$/, :border_width_overall ],
|
81
|
+
[ /^border-[trblxy](?:-\d+|\[\S+\])?$/, :border_width_side ],
|
82
|
+
[ /^border-(?:solid|dashed|dotted|double|none)$/, :border_style ],
|
83
|
+
[ /^border-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :border_color ],
|
78
84
|
|
79
85
|
# Radius
|
80
|
-
[/^rounded(?:-(?:none|sm|md|lg|xl|2xl|3xl|full|\[.+\]))?$/, :rounded_overall],
|
81
|
-
[/^rounded-(?:t|r|b|l|tl|tr|br|bl)-(?:none|sm|md|lg|xl|2xl|3xl|full|\[.+\])$/, :rounded_corner],
|
86
|
+
[ /^rounded(?:-(?:none|sm|md|lg|xl|2xl|3xl|full|\[.+\]))?$/, :rounded_overall ],
|
87
|
+
[ /^rounded-(?:t|r|b|l|tl|tr|br|bl)-(?:none|sm|md|lg|xl|2xl|3xl|full|\[.+\])$/, :rounded_corner ],
|
82
88
|
|
83
89
|
# Background
|
84
|
-
[/^bg-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :bg_color],
|
90
|
+
[ /^bg-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :bg_color ],
|
85
91
|
|
86
92
|
# Overflow & opacity
|
87
|
-
[/^overflow-(?:auto|hidden|visible|scroll|clip)$/, :overflow],
|
88
|
-
[/^overflow-[xy]-(?:auto|hidden|visible|scroll|clip)$/, :overflow_axis],
|
89
|
-
[/^opacity-(?:\d{1,3}|\[.+\])$/, :opacity]
|
93
|
+
[ /^overflow-(?:auto|hidden|visible|scroll|clip)$/, :overflow ],
|
94
|
+
[ /^overflow-[xy]-(?:auto|hidden|visible|scroll|clip)$/, :overflow_axis ],
|
95
|
+
[ /^opacity-(?:\d{1,3}|\[.+\])$/, :opacity ]
|
90
96
|
].freeze
|
91
97
|
|
92
98
|
class << self
|
@@ -94,9 +100,9 @@ module OkonomiUiKit
|
|
94
100
|
|
95
101
|
# "sm:hover:text-lg" -> ["sm:hover", "text-lg"]
|
96
102
|
def split_variants(token)
|
97
|
-
parts = token.split(
|
98
|
-
return ["", token] if parts.size == 1
|
99
|
-
[parts[0..-2].join(
|
103
|
+
parts = token.split(":")
|
104
|
+
return [ "", token ] if parts.size == 1
|
105
|
+
[ parts[0..-2].join(":"), parts[-1] ]
|
100
106
|
end
|
101
107
|
|
102
108
|
def conflict_group_for(base)
|
@@ -105,4 +111,4 @@ module OkonomiUiKit
|
|
105
111
|
end
|
106
112
|
end
|
107
113
|
end
|
108
|
-
end
|
114
|
+
end
|
@@ -8,74 +8,33 @@ module OkonomiUiKit
|
|
8
8
|
include ActionView::Helpers::TagHelper
|
9
9
|
include ActionView::Helpers::CaptureHelper
|
10
10
|
|
11
|
-
|
12
|
-
@template = template
|
13
|
-
end
|
14
|
-
|
15
|
-
def theme(t = {}, &block)
|
16
|
-
old_theme = get_theme
|
17
|
-
|
18
|
-
@_okonomi_ui_kit_theme = {}.merge(old_theme).merge(t || {})
|
19
|
-
|
20
|
-
yield(@_okonomi_ui_kit_theme)
|
11
|
+
attr_reader :template, :namespace
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def get_theme
|
26
|
-
@_okonomi_ui_kit_theme ||= OkonomiUiKit::Theme::DEFAULT_THEME
|
13
|
+
def initialize(template, namespace: OkonomiUiKit::Components)
|
14
|
+
@template = template
|
15
|
+
@namespace = namespace
|
27
16
|
end
|
28
17
|
|
29
|
-
def
|
30
|
-
|
31
|
-
get_theme.dig(:components, :link, :root) || '',
|
32
|
-
get_theme.dig(:components, :link, variant.to_sym, :root) || '',
|
33
|
-
get_theme.dig(:components, :link, variant.to_sym, :colors, color.to_sym) || '',
|
34
|
-
classes,
|
35
|
-
].join(' ')
|
36
|
-
end
|
18
|
+
def method_missing(method_name, *args, &block)
|
19
|
+
component = resolve_component(method_name)
|
37
20
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
cancel_text: cancel_text,
|
44
|
-
variant: variant,
|
45
|
-
size: size,
|
46
|
-
has_custom_actions: block_given?,
|
47
|
-
**options
|
48
|
-
}
|
49
|
-
@template.render("okonomi/modals/confirmation_modal", options: modal_options, ui: self, &block)
|
21
|
+
if component
|
22
|
+
component.render(*args, &block)
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
50
26
|
end
|
51
27
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
options[:data].map { |k, v| "data-#{k.to_s.dasherize}=\"#{v}\"" }.join(' ').html_safe
|
56
|
-
end
|
28
|
+
def resolve_component(name)
|
29
|
+
component_name = "#{namespace.name}::#{name.to_s.camelize}"
|
57
30
|
|
58
|
-
|
59
|
-
[
|
60
|
-
get_theme.dig(:components, :modal, :panel, :base),
|
61
|
-
get_theme.dig(:components, :modal, :panel, :sizes, size)
|
62
|
-
].compact.join(' ')
|
63
|
-
end
|
31
|
+
return nil unless Object.const_defined?(component_name)
|
64
32
|
|
65
|
-
|
66
|
-
[
|
67
|
-
get_theme.dig(:components, :modal, :icon, :wrapper),
|
68
|
-
get_theme.dig(:components, :modal, :icon, :variants, variant, :wrapper)
|
69
|
-
].compact.join(' ')
|
33
|
+
component_name.constantize.new(@template)
|
70
34
|
end
|
71
35
|
|
72
|
-
def
|
73
|
-
|
74
|
-
if Object.const_defined?(component_name)
|
75
|
-
return component_name.constantize.new(@template, get_theme).render(*args, &block)
|
76
|
-
else
|
77
|
-
super
|
78
|
-
end
|
36
|
+
def forms
|
37
|
+
@forms ||= self.class.new(@template, namespace: OkonomiUiKit::Components::Forms)
|
79
38
|
end
|
80
39
|
end
|
81
40
|
end
|
@@ -19,6 +19,12 @@ export default class extends Controller {
|
|
19
19
|
this.menuTarget.classList.add("hidden")
|
20
20
|
}
|
21
21
|
|
22
|
+
closeDeferred() {
|
23
|
+
setTimeout(() => {
|
24
|
+
this.close()
|
25
|
+
}, 50)
|
26
|
+
}
|
27
|
+
|
22
28
|
closeOnClickOutside(event) {
|
23
29
|
if (!this.element.contains(event.target)) {
|
24
30
|
this.close()
|
@@ -0,0 +1,76 @@
|
|
1
|
+
<div data-controller="modal"
|
2
|
+
data-modal-size-value="<%= options[:size] %>"
|
3
|
+
<% if options[:auto_open] %>data-modal-auto-open-value="true"<% end %>
|
4
|
+
class="relative z-10"
|
5
|
+
style="display: none;"
|
6
|
+
data-modal-target="container"
|
7
|
+
<%= component.modal_data_attributes(options) %>>
|
8
|
+
|
9
|
+
<!-- Backdrop -->
|
10
|
+
<div class="<%= component.style(:backdrop) %>"
|
11
|
+
data-modal-target="backdrop"
|
12
|
+
data-action="click->modal#close"
|
13
|
+
aria-hidden="true"></div>
|
14
|
+
|
15
|
+
<!-- Modal container -->
|
16
|
+
<div class="<%= component.style(:container) %>">
|
17
|
+
<div class="<%= component.style(:wrapper) %>">
|
18
|
+
<!-- Modal panel -->
|
19
|
+
<div class="<%= component.modal_panel_class(options[:size]) %>"
|
20
|
+
data-modal-target="panel"
|
21
|
+
role="dialog"
|
22
|
+
aria-modal="true"
|
23
|
+
aria-labelledby="modal-title">
|
24
|
+
|
25
|
+
<!-- Close button -->
|
26
|
+
<div class="<%= component.style(:close_button, :wrapper) %>">
|
27
|
+
<button type="button"
|
28
|
+
class="<%= component.style(:close_button, :button) %>"
|
29
|
+
data-action="click->modal#close">
|
30
|
+
<span class="sr-only">Close</span>
|
31
|
+
<%= ui.icon(component.style(:close_button, :icon, :file),
|
32
|
+
class: component.style(:close_button, :icon, :class)) %>
|
33
|
+
</button>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<!-- Content -->
|
37
|
+
<div class="<%= component.style(:content, :wrapper) %>">
|
38
|
+
<!-- Icon -->
|
39
|
+
<div class="<%= component.modal_icon_wrapper_class(options[:variant]) %>">
|
40
|
+
<%= ui.icon(component.style(:icon, :variants, options[:variant], :file),
|
41
|
+
class: component.modal_icon_class(options[:variant])) %>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<!-- Text content -->
|
45
|
+
<div class="<%= component.style(:content, :text_wrapper) %>">
|
46
|
+
<h3 id="modal-title" class="<%= component.style(:content, :title) %>">
|
47
|
+
<%= options[:title] %>
|
48
|
+
</h3>
|
49
|
+
<div class="<%= component.style(:content, :message) %>">
|
50
|
+
<p><%= options[:message] %></p>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<!-- Actions -->
|
56
|
+
<div class="<%= component.style(:actions, :wrapper) %>">
|
57
|
+
<% if options[:has_custom_actions] %>
|
58
|
+
<%= yield %>
|
59
|
+
<% else %>
|
60
|
+
<% button_color = options[:variant] == :warning ? :danger : options[:variant] %>
|
61
|
+
<%= ui.button_to options[:confirm_text], "#",
|
62
|
+
variant: :contained,
|
63
|
+
color: button_color,
|
64
|
+
class: "sm:ml-3 sm:w-auto",
|
65
|
+
data: { action: "click->modal#confirm" } %>
|
66
|
+
<%= ui.button_to options[:cancel_text], "#",
|
67
|
+
variant: :outlined,
|
68
|
+
color: :default,
|
69
|
+
class: "mt-3 sm:mt-0 sm:w-auto",
|
70
|
+
data: { action: "click->modal#close" } %>
|
71
|
+
<% end %>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
</div>
|