okonomi_ui_kit 0.1.7 → 0.1.9
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 +165 -7
- data/app/assets/builds/okonomi_ui_kit/application.tailwind.css +664 -187
- 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 +44 -21
- data/app/helpers/okonomi_ui_kit/components/alert.rb +1 -1
- data/app/helpers/okonomi_ui_kit/components/badge.rb +5 -5
- data/app/helpers/okonomi_ui_kit/components/breadcrumbs.rb +69 -0
- data/app/helpers/okonomi_ui_kit/components/button_base.rb +56 -0
- data/app/helpers/okonomi_ui_kit/components/button_tag.rb +23 -0
- data/app/helpers/okonomi_ui_kit/components/button_to.rb +4 -15
- 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/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 +36 -0
- data/app/helpers/okonomi_ui_kit/components/link_to.rb +8 -19
- data/app/helpers/okonomi_ui_kit/components/navigation.rb +98 -0
- data/app/helpers/okonomi_ui_kit/components/page.rb +8 -8
- data/app/helpers/okonomi_ui_kit/components/table.rb +9 -10
- 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/config.rb +5 -1
- 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 +114 -0
- data/app/helpers/okonomi_ui_kit/ui_helper.rb +17 -58
- data/app/views/okonomi/components/breadcrumbs/_breadcrumbs.html.erb +46 -0
- data/app/views/okonomi/components/confirmation_modal/_confirmation_modal.html.erb +76 -0
- data/app/views/okonomi/components/forms/check_box_with_label/_check_box_with_label.html.erb +6 -0
- data/app/views/okonomi/components/forms/field/_field.html.erb +3 -0
- 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/icon/_icon.html.erb +38 -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/forms/tailwind/_checkbox_label.html.erb +2 -2
- data/app/views/okonomi/forms/tailwind/_field.html.erb +6 -6
- 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 -3
- data/lib/okonomi_ui_kit/version.rb +1 -1
- metadata +43 -12
- data/app/helpers/okonomi_ui_kit/breadcrumbs_helper.rb +0 -60
- data/app/helpers/okonomi_ui_kit/icon_helper.rb +0 -39
- data/app/helpers/okonomi_ui_kit/navigation_helper.rb +0 -72
- data/app/helpers/okonomi_ui_kit/theme.rb +0 -159
- 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
@@ -1,4 +1,12 @@
|
|
1
1
|
module OkonomiUiKit
|
2
2
|
module ApplicationHelper
|
3
|
+
def active_link_to(path, options = {}, &block)
|
4
|
+
path_to_check = path.split("?").first
|
5
|
+
if (options[:exact] && request.path == path_to_check) || (!options[:exact] && request.path.include?(path_to_check))
|
6
|
+
options[:class] = options[:active_class].presence || [ options[:class], "active" ].compact.join(" ")
|
7
|
+
end
|
8
|
+
|
9
|
+
link_to(path, options, &block)
|
10
|
+
end
|
3
11
|
end
|
4
12
|
end
|
@@ -3,7 +3,7 @@ module OkonomiUiKit
|
|
3
3
|
def attribute_section(title:, description: nil, **options, &block)
|
4
4
|
builder = AttributeSectionBuilder.new(self)
|
5
5
|
|
6
|
-
render
|
6
|
+
render "okonomi/attribute_sections/section",
|
7
7
|
builder: builder,
|
8
8
|
title: title,
|
9
9
|
description: description,
|
@@ -22,11 +22,11 @@ module OkonomiUiKit
|
|
22
22
|
def attribute(label, value = nil, **options, &block)
|
23
23
|
content = if block_given?
|
24
24
|
capture(&block)
|
25
|
-
|
25
|
+
elsif value.respond_to?(:call)
|
26
26
|
value.call
|
27
|
-
|
27
|
+
else
|
28
28
|
value
|
29
|
-
|
29
|
+
end
|
30
30
|
|
31
31
|
tag.div(class: "py-6 sm:grid sm:grid-cols-3 sm:gap-4") do
|
32
32
|
dt_content = tag.dt(label, class: "text-sm font-medium text-gray-900")
|
@@ -47,4 +47,4 @@ module OkonomiUiKit
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
-
end
|
50
|
+
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module OkonomiUiKit
|
2
2
|
class Component
|
3
|
-
attr_reader :view
|
3
|
+
attr_reader :view
|
4
4
|
|
5
|
-
def initialize(view
|
5
|
+
def initialize(view)
|
6
6
|
@view = view
|
7
|
-
@theme = theme || OkonomiUiKit::Theme::DEFAULT_THEME
|
8
7
|
end
|
9
8
|
|
10
9
|
def template_path
|
11
|
-
"okonomi/
|
10
|
+
[ self.class.name.underscore.gsub("okonomi_ui_kit/", "okonomi/"), name ].join("/")
|
12
11
|
end
|
13
12
|
|
14
13
|
def name
|
@@ -30,7 +29,7 @@ module OkonomiUiKit
|
|
30
29
|
internal_styles = internal_styles_registry[internal_name] || {}
|
31
30
|
config_styles = config_styles_registry[config_name] || {}
|
32
31
|
|
33
|
-
{}
|
32
|
+
deep_merge({}, internal_styles, config_styles)
|
34
33
|
end
|
35
34
|
|
36
35
|
def internal_styles_registry
|
@@ -45,36 +44,60 @@ module OkonomiUiKit
|
|
45
44
|
:default
|
46
45
|
end
|
47
46
|
|
48
|
-
def self.
|
49
|
-
|
47
|
+
def self.register_styles(theme = :default, &block)
|
48
|
+
styles = block.call if block_given?
|
50
49
|
|
51
|
-
|
50
|
+
raise ArgumentError, "Styles must be a Hash" unless styles.is_a?(Hash)
|
51
|
+
|
52
|
+
internal_styles_registry[theme] ||= {}
|
53
|
+
internal_styles_registry[theme] = deep_merge(internal_styles_registry[theme], styles)
|
52
54
|
end
|
53
55
|
|
54
|
-
def self.
|
55
|
-
|
56
|
+
def self.internal_styles_registry
|
57
|
+
@internal_styles_registry ||= deep_merge({}, parent_styles_registry)
|
58
|
+
end
|
56
59
|
|
57
|
-
|
60
|
+
def self.parent_styles_registry
|
61
|
+
if superclass.respond_to?(:internal_styles_registry)
|
62
|
+
superclass.internal_styles_registry
|
63
|
+
else
|
64
|
+
{}
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
|
-
def self.
|
61
|
-
|
68
|
+
def self.config_styles_registry
|
69
|
+
@config_styles_registry ||= config_classes.reverse.reduce({}) do |hash, klass|
|
70
|
+
deep_merge(hash, klass.styles_registry)
|
71
|
+
end
|
62
72
|
end
|
63
73
|
|
64
|
-
def self.
|
65
|
-
|
74
|
+
def self.config_classes
|
75
|
+
@config_classes ||= resolve_config_classes
|
66
76
|
end
|
67
77
|
|
68
|
-
def self.
|
69
|
-
|
78
|
+
def self.resolve_config_classes
|
79
|
+
classes = []
|
80
|
+
classes << Object.const_get(config_class_name) if config_class?
|
81
|
+
classes += superclass.config_classes if superclass <= OkonomiUiKit::Component
|
70
82
|
|
71
|
-
|
83
|
+
classes.compact
|
84
|
+
end
|
72
85
|
|
73
|
-
|
86
|
+
def self.config_class_name
|
87
|
+
"#{config_namespace.name}::#{name.demodulize}"
|
74
88
|
end
|
75
89
|
|
76
|
-
def self.
|
77
|
-
|
90
|
+
def self.config_namespace
|
91
|
+
OkonomiUiKit::Configs
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.config_class?
|
95
|
+
Object.const_defined?(config_class_name)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.deep_merge(*hashes)
|
99
|
+
OkonomiUiKit::TWMerge.deep_merge_all(*hashes)
|
78
100
|
end
|
101
|
+
delegate :deep_merge, to: :class
|
79
102
|
end
|
80
103
|
end
|
@@ -2,7 +2,7 @@ module OkonomiUiKit
|
|
2
2
|
module Components
|
3
3
|
class Alert < OkonomiUiKit::Component
|
4
4
|
def render(title, options = {}, &block)
|
5
|
-
view.render(template_path, title
|
5
|
+
view.render(template_path, title: title, options: options.with_indifferent_access, &block)
|
6
6
|
end
|
7
7
|
end
|
8
8
|
end
|
@@ -3,13 +3,13 @@ module OkonomiUiKit
|
|
3
3
|
class Badge < OkonomiUiKit::Component
|
4
4
|
def render(text, options = {})
|
5
5
|
options = options.with_indifferent_access
|
6
|
-
severity = (options.delete(:severity) || :default).to_sym
|
7
|
-
|
6
|
+
severity = (options.delete(:severity) || options.delete(:variant) || :default).to_sym
|
7
|
+
|
8
8
|
classes = [
|
9
9
|
style(:base),
|
10
|
-
style(:severities, severity) ||
|
11
|
-
options.delete(:class) ||
|
12
|
-
].reject(&:blank?).join(
|
10
|
+
style(:severities, severity) || "",
|
11
|
+
options.delete(:class) || ""
|
12
|
+
].reject(&:blank?).join(" ")
|
13
13
|
|
14
14
|
view.tag.span(text, class: classes, **options)
|
15
15
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OkonomiUiKit
|
4
|
+
module Components
|
5
|
+
class Breadcrumbs < Component
|
6
|
+
register_styles do
|
7
|
+
{
|
8
|
+
base: "flex",
|
9
|
+
container: "isolate flex -space-x-px rounded-lg shadow-sm",
|
10
|
+
nav: "",
|
11
|
+
list: "flex items-center space-x-4",
|
12
|
+
item: {
|
13
|
+
base: "",
|
14
|
+
first: "",
|
15
|
+
last: "",
|
16
|
+
current: ""
|
17
|
+
},
|
18
|
+
link: {
|
19
|
+
base: "ml-4 text-sm font-medium text-gray-500 hover:text-gray-700",
|
20
|
+
first: "text-sm font-medium text-gray-500 hover:text-gray-700",
|
21
|
+
current: "ml-4 text-sm font-medium text-gray-500"
|
22
|
+
},
|
23
|
+
separator: {
|
24
|
+
base: "size-5 shrink-0 text-gray-400",
|
25
|
+
wrapper: ""
|
26
|
+
},
|
27
|
+
icon: "size-5 text-gray-400"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(template)
|
32
|
+
super
|
33
|
+
@items = []
|
34
|
+
@builder = BreadcrumbBuilder.new(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
def render(options = {}, &block)
|
38
|
+
return "" if block.nil?
|
39
|
+
|
40
|
+
block.call(@builder)
|
41
|
+
view.render("okonomi/components/breadcrumbs/breadcrumbs",
|
42
|
+
component: self,
|
43
|
+
items: @items,
|
44
|
+
options: options
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_item(text, path = nil, current: false, icon: nil)
|
49
|
+
@items << {
|
50
|
+
text: text,
|
51
|
+
path: path,
|
52
|
+
current: current,
|
53
|
+
icon: icon
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
class BreadcrumbBuilder
|
58
|
+
def initialize(component)
|
59
|
+
@component = component
|
60
|
+
end
|
61
|
+
|
62
|
+
def link(text, path = nil, current: false, icon: nil, **options)
|
63
|
+
# Ignore extra options for now
|
64
|
+
@component.add_item(text, path, current: current, icon: icon)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module OkonomiUiKit
|
2
|
+
module Components
|
3
|
+
class ButtonBase < OkonomiUiKit::Component
|
4
|
+
def build_button_class(variant:, color:, classes: "")
|
5
|
+
[
|
6
|
+
style(:root) || "",
|
7
|
+
style(variant.to_sym, :root) || "",
|
8
|
+
style(variant.to_sym, :colors, color.to_sym) || "",
|
9
|
+
classes
|
10
|
+
].reject(&:blank?).join(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
register_styles :default do
|
14
|
+
{
|
15
|
+
root: "hover:cursor-pointer text-sm",
|
16
|
+
outlined: {
|
17
|
+
root: "inline-flex border items-center justify-center px-2 py-1 rounded-md font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
|
18
|
+
colors: {
|
19
|
+
default: "bg-white text-default-700 border-default-700 hover:bg-default-50",
|
20
|
+
primary: "bg-white text-primary-600 border-primary-600 hover:bg-primary-50",
|
21
|
+
secondary: "bg-white text-secondary-600 border-secondary-600 hover:bg-secondary-50",
|
22
|
+
success: "bg-white text-success-600 border-success-600 hover:bg-success-50",
|
23
|
+
danger: "bg-white text-danger-600 border-danger-600 hover:bg-danger-50",
|
24
|
+
warning: "bg-white text-warning-600 border-warning-600 hover:bg-warning-50",
|
25
|
+
info: "bg-white text-info-600 border-info-600 hover:bg-info-50"
|
26
|
+
}
|
27
|
+
},
|
28
|
+
contained: {
|
29
|
+
root: "inline-flex border items-center justify-center px-2 py-1 rounded-md font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
|
30
|
+
colors: {
|
31
|
+
default: "border-default-700 bg-default-600 text-white hover:bg-default-700",
|
32
|
+
primary: "border-primary-700 bg-primary-600 text-white hover:bg-primary-700",
|
33
|
+
secondary: "border-secondary-700 bg-secondary-600 text-white hover:bg-secondary-700",
|
34
|
+
success: "border-success-700 bg-success-600 text-white hover:bg-success-700",
|
35
|
+
danger: "border-danger-700 bg-danger-600 text-white hover:bg-danger-700",
|
36
|
+
warning: "border-warning-700 bg-warning-600 text-white hover:bg-warning-700",
|
37
|
+
info: "border-info-700 bg-info-600 text-white hover:bg-info-700"
|
38
|
+
}
|
39
|
+
},
|
40
|
+
text: {
|
41
|
+
root: "text-base",
|
42
|
+
colors: {
|
43
|
+
default: "text-default-700 hover:underline",
|
44
|
+
primary: "text-primary-600 hover:underline",
|
45
|
+
secondary: "text-secondary-600 hover:underline",
|
46
|
+
success: "text-success-600 hover:underline",
|
47
|
+
danger: "text-danger-600 hover:underline",
|
48
|
+
warning: "text-warning-600 hover:underline",
|
49
|
+
info: "text-info-600 hover:underline"
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OkonomiUiKit
|
2
|
+
module Components
|
3
|
+
class ButtonTag < OkonomiUiKit::Components::ButtonBase
|
4
|
+
def render(name = nil, options = {}, &block)
|
5
|
+
options, name = options, block if block_given?
|
6
|
+
|
7
|
+
options ||= {}
|
8
|
+
options = options.with_indifferent_access
|
9
|
+
|
10
|
+
variant = (options.delete(:variant) || "contained").to_sym
|
11
|
+
color = (options.delete(:color) || "default").to_sym
|
12
|
+
|
13
|
+
options[:class] = build_button_class(variant: variant, color: color, classes: options[:class])
|
14
|
+
|
15
|
+
if block_given?
|
16
|
+
view.button_tag(options, &block)
|
17
|
+
else
|
18
|
+
view.button_tag(name, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module OkonomiUiKit
|
2
2
|
module Components
|
3
|
-
class ButtonTo < OkonomiUiKit::
|
3
|
+
class ButtonTo < OkonomiUiKit::Components::ButtonBase
|
4
4
|
def render(name = nil, options = nil, html_options = nil, &block)
|
5
5
|
html_options, options, name = options, name, block if block_given?
|
6
6
|
|
7
7
|
html_options ||= {}
|
8
8
|
html_options = html_options.with_indifferent_access
|
9
9
|
|
10
|
-
variant = (html_options.delete(:variant) ||
|
11
|
-
color = (html_options.delete(:color) ||
|
10
|
+
variant = (html_options.delete(:variant) || "contained").to_sym
|
11
|
+
color = (html_options.delete(:color) || "default").to_sym
|
12
12
|
|
13
13
|
html_options[:class] = build_button_class(variant: variant, color: color, classes: html_options[:class])
|
14
14
|
|
@@ -18,17 +18,6 @@ module OkonomiUiKit
|
|
18
18
|
view.button_to(name, options, html_options)
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def build_button_class(variant:, color:, classes: '')
|
25
|
-
[
|
26
|
-
theme.dig(:components, :link, :root) || '',
|
27
|
-
theme.dig(:components, :link, variant.to_sym, :root) || '',
|
28
|
-
theme.dig(:components, :link, variant.to_sym, :colors, color.to_sym) || '',
|
29
|
-
classes,
|
30
|
-
].reject(&:blank?).join(' ')
|
31
|
-
end
|
32
21
|
end
|
33
22
|
end
|
34
|
-
end
|
23
|
+
end
|
@@ -8,61 +8,65 @@ module OkonomiUiKit
|
|
8
8
|
|
9
9
|
# Extract component-specific options
|
10
10
|
language = options.delete(:language) || options.delete(:lang)
|
11
|
-
variant = (options.delete(:variant) ||
|
12
|
-
size = (options.delete(:size) ||
|
11
|
+
variant = (options.delete(:variant) || "default").to_sym
|
12
|
+
size = (options.delete(:size) || "default").to_sym
|
13
13
|
wrap = options.delete(:wrap) != false # Default to true
|
14
14
|
|
15
15
|
# Build classes
|
16
16
|
classes = build_classes(variant: variant, size: size, wrap: wrap, custom_class: options.delete(:class))
|
17
17
|
|
18
18
|
# Escape HTML entities in content
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
raw_content = if block_given?
|
20
|
+
view.capture(&block)
|
21
|
+
elsif content
|
22
|
+
content
|
23
|
+
else
|
24
|
+
""
|
25
|
+
end
|
26
|
+
|
27
|
+
escaped_content = html_escape(raw_content)
|
26
28
|
|
27
29
|
view.render(
|
28
30
|
template_path,
|
29
|
-
content: escaped_content
|
31
|
+
content: escaped_content,
|
30
32
|
options: options,
|
31
33
|
classes: classes,
|
32
34
|
language: language
|
33
35
|
)
|
34
36
|
end
|
35
37
|
|
38
|
+
register_styles :default do
|
39
|
+
{
|
40
|
+
base: "",
|
41
|
+
variants: {
|
42
|
+
default: "bg-gray-900 text-gray-100 p-4 rounded-lg",
|
43
|
+
inline: "bg-gray-100 text-gray-900 px-1 py-0.5 rounded text-sm font-mono",
|
44
|
+
minimal: "bg-gray-900 text-gray-100 p-3 rounded text-xs"
|
45
|
+
},
|
46
|
+
sizes: {
|
47
|
+
xs: "text-xs",
|
48
|
+
sm: "text-sm",
|
49
|
+
default: "text-sm",
|
50
|
+
lg: "text-base"
|
51
|
+
},
|
52
|
+
wrap: {
|
53
|
+
true: "overflow-x-auto",
|
54
|
+
false: "overflow-hidden"
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
36
59
|
private
|
37
60
|
|
38
61
|
def build_classes(variant:, size:, wrap:, custom_class: nil)
|
39
|
-
base_classes =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
"bg-gray-900 text-gray-100 p-3 rounded text-xs"
|
46
|
-
else
|
47
|
-
# :default
|
48
|
-
"bg-gray-900 text-gray-100 p-4 rounded-lg"
|
49
|
-
end
|
50
|
-
|
51
|
-
size_classes = case size
|
52
|
-
when :xs
|
53
|
-
"text-xs"
|
54
|
-
when :sm
|
55
|
-
"text-sm"
|
56
|
-
when :lg
|
57
|
-
"text-base"
|
58
|
-
else
|
59
|
-
# :default
|
60
|
-
"text-sm"
|
61
|
-
end
|
62
|
-
|
63
|
-
wrap_classes = wrap ? "overflow-x-auto" : "overflow-hidden"
|
62
|
+
base_classes = style(:base) || ""
|
63
|
+
variant_classes = style(:variants, variant) || ""
|
64
|
+
size_classes = style(:sizes, size) || ""
|
65
|
+
# Convert boolean wrap to symbol for hash access
|
66
|
+
wrap_key = wrap ? :true : :false
|
67
|
+
wrap_classes = style(:wrap, wrap_key) || ""
|
64
68
|
|
65
|
-
[base_classes, variant_classes, size_classes, wrap_classes, custom_class].
|
69
|
+
[ base_classes, variant_classes, size_classes, wrap_classes, custom_class ].reject(&:blank?).join(" ")
|
66
70
|
end
|
67
71
|
|
68
72
|
def html_escape(content)
|
@@ -70,4 +74,4 @@ module OkonomiUiKit
|
|
70
74
|
end
|
71
75
|
end
|
72
76
|
end
|
73
|
-
end
|
77
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module OkonomiUiKit
|
2
|
+
module Components
|
3
|
+
class ConfirmationModal < OkonomiUiKit::Component
|
4
|
+
def render(options = {}, &block)
|
5
|
+
options = options.with_indifferent_access
|
6
|
+
|
7
|
+
# Extract and validate required options
|
8
|
+
title = options.fetch(:title) { raise ArgumentError, "title is required" }
|
9
|
+
message = options.fetch(:message) { raise ArgumentError, "message is required" }
|
10
|
+
|
11
|
+
# Extract optional parameters with defaults
|
12
|
+
confirm_text = options.delete(:confirm_text) || "Confirm"
|
13
|
+
cancel_text = options.delete(:cancel_text) || "Cancel"
|
14
|
+
variant = (options.delete(:variant) || :warning).to_sym
|
15
|
+
size = (options.delete(:size) || :md).to_sym
|
16
|
+
auto_open = options.delete(:auto_open) || false
|
17
|
+
|
18
|
+
# Build component options
|
19
|
+
modal_options = {
|
20
|
+
title: title,
|
21
|
+
message: message,
|
22
|
+
confirm_text: confirm_text,
|
23
|
+
cancel_text: cancel_text,
|
24
|
+
variant: variant,
|
25
|
+
size: size,
|
26
|
+
auto_open: auto_open,
|
27
|
+
has_custom_actions: block_given?,
|
28
|
+
data: options.delete(:data) || {}
|
29
|
+
}.merge(options)
|
30
|
+
|
31
|
+
view.render(template_path, component: self, options: modal_options, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Register default styles for the confirmation modal
|
35
|
+
register_styles :default do
|
36
|
+
{
|
37
|
+
# Modal container and backdrop
|
38
|
+
backdrop: "fixed inset-0 bg-gray-500/75 transition-opacity duration-300 ease-out opacity-0",
|
39
|
+
container: "fixed inset-0 z-10 w-screen overflow-y-auto",
|
40
|
+
wrapper: "flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0",
|
41
|
+
|
42
|
+
# Modal panel
|
43
|
+
panel: {
|
44
|
+
base: "relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all duration-300 ease-out sm:my-8 sm:w-full sm:p-6 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
|
45
|
+
sizes: {
|
46
|
+
sm: "sm:max-w-sm",
|
47
|
+
md: "sm:max-w-lg",
|
48
|
+
lg: "sm:max-w-2xl",
|
49
|
+
xl: "sm:max-w-4xl"
|
50
|
+
}
|
51
|
+
},
|
52
|
+
|
53
|
+
# Close button
|
54
|
+
close_button: {
|
55
|
+
wrapper: "absolute top-0 right-0 hidden pt-4 pr-4 sm:block",
|
56
|
+
button: "rounded-md bg-white text-gray-400 hover:text-gray-500 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-none",
|
57
|
+
icon: {
|
58
|
+
file: "heroicons/outline/x-mark",
|
59
|
+
class: "size-6"
|
60
|
+
}
|
61
|
+
},
|
62
|
+
|
63
|
+
# Icon configuration
|
64
|
+
icon: {
|
65
|
+
wrapper: "mx-auto flex size-12 shrink-0 items-center justify-center rounded-full sm:mx-0 sm:size-10",
|
66
|
+
class: "size-6",
|
67
|
+
variants: {
|
68
|
+
warning: {
|
69
|
+
wrapper: "bg-red-100",
|
70
|
+
icon: "text-red-600",
|
71
|
+
file: "heroicons/outline/exclamation-triangle"
|
72
|
+
},
|
73
|
+
info: {
|
74
|
+
wrapper: "bg-blue-100",
|
75
|
+
icon: "text-blue-600",
|
76
|
+
file: "heroicons/outline/information-circle"
|
77
|
+
},
|
78
|
+
success: {
|
79
|
+
wrapper: "bg-green-100",
|
80
|
+
icon: "text-green-600",
|
81
|
+
file: "heroicons/outline/check-circle"
|
82
|
+
}
|
83
|
+
}
|
84
|
+
},
|
85
|
+
|
86
|
+
# Content styling
|
87
|
+
content: {
|
88
|
+
wrapper: "sm:flex sm:items-start",
|
89
|
+
text_wrapper: "mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",
|
90
|
+
title: "text-base font-semibold text-gray-900",
|
91
|
+
message: "mt-2 text-sm text-gray-500"
|
92
|
+
},
|
93
|
+
|
94
|
+
# Actions container
|
95
|
+
actions: {
|
96
|
+
wrapper: "mt-5 sm:mt-4 sm:flex sm:flex-row-reverse"
|
97
|
+
}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Helper methods to build classes from styles
|
102
|
+
def modal_panel_class(size)
|
103
|
+
[
|
104
|
+
style(:panel, :base),
|
105
|
+
style(:panel, :sizes, size)
|
106
|
+
].compact.join(" ")
|
107
|
+
end
|
108
|
+
|
109
|
+
def modal_icon_wrapper_class(variant)
|
110
|
+
[
|
111
|
+
style(:icon, :wrapper),
|
112
|
+
style(:icon, :variants, variant, :wrapper)
|
113
|
+
].compact.join(" ")
|
114
|
+
end
|
115
|
+
|
116
|
+
def modal_icon_class(variant)
|
117
|
+
[
|
118
|
+
style(:icon, :class),
|
119
|
+
style(:icon, :variants, variant, :icon)
|
120
|
+
].compact.join(" ")
|
121
|
+
end
|
122
|
+
|
123
|
+
def modal_data_attributes(options)
|
124
|
+
return "" unless options[:data]
|
125
|
+
|
126
|
+
options[:data].map { |k, v| "data-#{k.to_s.dasherize}=\"#{v}\"" }.join(" ").html_safe
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module OkonomiUiKit
|
2
|
+
module Components
|
3
|
+
module Forms
|
4
|
+
class CheckBoxWithLabel < OkonomiUiKit::FormComponent
|
5
|
+
def render(form, method, options = {}, checked_value = true, unchecked_value = false)
|
6
|
+
options = options.with_indifferent_access
|
7
|
+
|
8
|
+
view.content_tag(:div, class: style(:wrapper)) do
|
9
|
+
view.concat form.check_box(
|
10
|
+
method,
|
11
|
+
{
|
12
|
+
class: style(:input, :root)
|
13
|
+
}.merge(options || {}),
|
14
|
+
checked_value,
|
15
|
+
unchecked_value
|
16
|
+
)
|
17
|
+
view.concat view.render(template_path, component: self, method: method, options: options, form: form)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
register_styles :default do
|
22
|
+
{
|
23
|
+
wrapper: "flex gap-x-3",
|
24
|
+
input: {
|
25
|
+
root: "size-4 rounded border-gray-300 text-primary-600 focus:ring-primary-600"
|
26
|
+
},
|
27
|
+
label: {
|
28
|
+
root: "text-sm/6 font-medium text-gray-900"
|
29
|
+
},
|
30
|
+
hint: {
|
31
|
+
root: "text-gray-500"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|