okonomi_ui_kit 0.1.6 → 0.1.8

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +163 -7
  3. data/app/assets/builds/okonomi_ui_kit/application.tailwind.css +292 -4
  4. data/app/helpers/okonomi_ui_kit/component.rb +81 -0
  5. data/app/helpers/okonomi_ui_kit/components/badge.rb +21 -16
  6. data/app/helpers/okonomi_ui_kit/components/breadcrumbs.rb +69 -0
  7. data/app/helpers/okonomi_ui_kit/components/button_base.rb +56 -0
  8. data/app/helpers/okonomi_ui_kit/components/button_tag.rb +23 -0
  9. data/app/helpers/okonomi_ui_kit/components/button_to.rb +23 -0
  10. data/app/helpers/okonomi_ui_kit/components/code.rb +73 -0
  11. data/app/helpers/okonomi_ui_kit/components/icon.rb +36 -0
  12. data/app/helpers/okonomi_ui_kit/components/link_to.rb +23 -0
  13. data/app/helpers/okonomi_ui_kit/components/page.rb +247 -0
  14. data/app/helpers/okonomi_ui_kit/components/table.rb +207 -0
  15. data/app/helpers/okonomi_ui_kit/components/typography.rb +29 -3
  16. data/app/helpers/okonomi_ui_kit/config.rb +20 -0
  17. data/app/helpers/okonomi_ui_kit/form_builder.rb +2 -2
  18. data/app/helpers/okonomi_ui_kit/t_w_merge.rb +108 -0
  19. data/app/helpers/okonomi_ui_kit/theme.rb +3 -26
  20. data/app/helpers/okonomi_ui_kit/ui_helper.rb +0 -40
  21. data/app/views/okonomi/components/breadcrumbs/_breadcrumbs.html.erb +46 -0
  22. data/app/views/okonomi/components/code/_code.html.erb +1 -0
  23. data/app/views/okonomi/components/icon/_icon.html.erb +38 -0
  24. data/app/views/okonomi/components/page/_page.html.erb +5 -0
  25. data/app/views/okonomi/components/table/_table.html.erb +3 -0
  26. data/app/views/okonomi/forms/tailwind/_upload_field.html.erb +2 -2
  27. data/app/views/okonomi/modals/_confirmation_modal.html.erb +2 -2
  28. data/app/views/okonomi/navigation/_link.html.erb +1 -1
  29. data/lib/okonomi_ui_kit/engine.rb +0 -5
  30. data/lib/okonomi_ui_kit/version.rb +1 -1
  31. metadata +18 -7
  32. data/app/helpers/okonomi_ui_kit/badge_helper.rb +0 -23
  33. data/app/helpers/okonomi_ui_kit/breadcrumbs_helper.rb +0 -60
  34. data/app/helpers/okonomi_ui_kit/icon_helper.rb +0 -39
  35. data/app/helpers/okonomi_ui_kit/page_builder_helper.rb +0 -217
  36. data/app/helpers/okonomi_ui_kit/table_helper.rb +0 -158
@@ -0,0 +1,207 @@
1
+ module OkonomiUiKit
2
+ module Components
3
+ class Table < OkonomiUiKit::Component
4
+ def render(options = {}, &block)
5
+ options = options.with_indifferent_access
6
+ variant = (options.delete(:variant) || :default).to_sym
7
+
8
+ builder = TableBuilder.new(view, theme, self, variant)
9
+ view.render(template_path, builder: builder, options: options, &block)
10
+ end
11
+
12
+ register_styles :default do
13
+ {
14
+ default: {
15
+ body: {
16
+ base: "divide-y divide-gray-200 bg-white"
17
+ },
18
+ th: {
19
+ base: "text-sm font-semibold text-gray-900",
20
+ first: "py-3.5 pr-3",
21
+ last: "relative py-3.5",
22
+ middle: "pl-3 pr-3 py-3.5"
23
+ },
24
+ td: {
25
+ base: "text-sm whitespace-nowrap",
26
+ first: "py-4 pr-3 font-medium text-gray-900",
27
+ last: "relative py-4 font-medium",
28
+ middle: "pl-3 pr-3 py-4 text-gray-500"
29
+ },
30
+ alignment: {
31
+ left: "text-left",
32
+ center: "text-center",
33
+ right: "text-right"
34
+ },
35
+ empty_state: {
36
+ wrapper: "text-center py-8",
37
+ icon: "mx-auto h-12 w-12 text-gray-400",
38
+ title: "mt-2 text-sm font-medium text-gray-900",
39
+ subtitle: "mt-1 text-sm text-gray-500",
40
+ cell: "text-center py-8 text-gray-500"
41
+ }
42
+ }
43
+ }
44
+ end
45
+ end
46
+
47
+ class TableBuilder
48
+ include ActionView::Helpers::TagHelper
49
+ include ActionView::Helpers::CaptureHelper
50
+
51
+ def initialize(template, theme, style_provider, variant = :default)
52
+ @template = template
53
+ @theme = theme
54
+ @style_provider = style_provider
55
+ @variant = variant
56
+ @current_row_cells = []
57
+ @in_header = false
58
+ @in_body = false
59
+ end
60
+
61
+ def head(&block)
62
+ @in_header = true
63
+ @in_body = false
64
+ result = tag.thead(&block)
65
+ @in_header = false
66
+ result
67
+ end
68
+
69
+ def body(&block)
70
+ @in_header = false
71
+ @in_body = true
72
+ result = tag.tbody(class: style(:body, :base), &block)
73
+ @in_body = false
74
+ result
75
+ end
76
+
77
+ def tr(&block)
78
+ @current_row_cells = []
79
+
80
+ # Collect all cells first
81
+ yield if block_given?
82
+
83
+ # Now render each cell with proper first/last detection
84
+ rendered_cells = @current_row_cells.map.with_index do |cell, index|
85
+ is_first = index == 0
86
+ is_last = index == @current_row_cells.length - 1
87
+
88
+ if cell[:type] == :th
89
+ render_th(cell, is_first, is_last)
90
+ else
91
+ render_td(cell, is_first, is_last)
92
+ end
93
+ end
94
+
95
+ result = tag.tr do
96
+ @template.safe_join(rendered_cells)
97
+ end
98
+
99
+ @current_row_cells = []
100
+ result
101
+ end
102
+
103
+ def th(scope: "col", align: :left, **options, &block)
104
+ content = capture(&block) if block_given?
105
+
106
+ # Store cell data for later processing in tr
107
+ cell = { type: :th, scope: scope, align: align, options: options, content: content }
108
+ @current_row_cells << cell
109
+
110
+ # Return empty string for now, actual rendering happens in tr
111
+ ""
112
+ end
113
+
114
+ def td(align: :left, **options, &block)
115
+ content = capture(&block) if block_given?
116
+
117
+ # Store cell data for later processing in tr
118
+ cell = { type: :td, align: align, options: options, content: content }
119
+ @current_row_cells << cell
120
+
121
+ # Return empty string for now, actual rendering happens in tr
122
+ ""
123
+ end
124
+
125
+ def empty_state(title: "No records found", icon: "heroicons/outline/document", colspan: nil, &block)
126
+ content = if block_given?
127
+ capture(&block)
128
+ else
129
+ tag.div(class: style(:empty_state, :wrapper)) do
130
+ icon_content = if @template.respond_to?(:ui)
131
+ @template.ui.icon(icon, class: style(:empty_state, :icon))
132
+ else
133
+ tag.div(class: style(:empty_state, :icon))
134
+ end
135
+
136
+ icon_content + tag.p(title, class: style(:empty_state, :title)) +
137
+ tag.p("Get started by creating a new record.", class: style(:empty_state, :subtitle))
138
+ end
139
+ end
140
+
141
+ tr do
142
+ td(colspan: colspan, class: style(:empty_state, :cell)) do
143
+ content
144
+ end
145
+ end
146
+ end
147
+
148
+ private
149
+
150
+ def tag
151
+ @template.tag
152
+ end
153
+
154
+ def capture(*args, &block)
155
+ @template.capture(*args, &block)
156
+ end
157
+
158
+ def render_th(cell, is_first, is_last)
159
+ align_class = style(:alignment, cell[:align]) || style(:alignment, :left)
160
+
161
+ position_class = if is_first
162
+ style(:th, :first)
163
+ elsif is_last
164
+ style(:th, :last)
165
+ else
166
+ style(:th, :middle)
167
+ end
168
+
169
+ classes = [
170
+ style(:th, :base),
171
+ position_class,
172
+ align_class,
173
+ cell[:options][:class]
174
+ ].compact.join(' ')
175
+
176
+ options = cell[:options].except(:class)
177
+ tag.th(cell[:content], scope: cell[:scope], class: classes, **options)
178
+ end
179
+
180
+ def render_td(cell, is_first, is_last)
181
+ align_class = style(:alignment, cell[:align]) || style(:alignment, :left)
182
+
183
+ position_class = if is_first
184
+ style(:td, :first)
185
+ elsif is_last
186
+ style(:td, :last)
187
+ else
188
+ style(:td, :middle)
189
+ end
190
+
191
+ classes = [
192
+ style(:td, :base),
193
+ position_class,
194
+ align_class,
195
+ cell[:options][:class]
196
+ ].compact.join(' ')
197
+
198
+ options = cell[:options].except(:class)
199
+ tag.td(cell[:content], class: classes, **options)
200
+ end
201
+
202
+ def style(*keys)
203
+ @style_provider.style(@variant, *keys)
204
+ end
205
+ end
206
+ end
207
+ end
@@ -20,10 +20,10 @@ module OkonomiUiKit
20
20
  variant = (options.delete(:variant) || 'body1').to_sym
21
21
  component = (TYPOGRAPHY_COMPONENTS[variant] || 'span').to_s
22
22
  color = (options.delete(:color) || 'default').to_sym
23
-
23
+
24
24
  classes = [
25
- theme.dig(:components, :typography, :variants, variant) || '',
26
- theme.dig(:components, :typography, :colors, color) || '',
25
+ style(:variants, variant) || '',
26
+ style(:colors, color) || '',
27
27
  options.delete(:class) || ''
28
28
  ].reject(&:blank?).join(' ')
29
29
 
@@ -37,6 +37,32 @@ module OkonomiUiKit
37
37
  &block
38
38
  )
39
39
  end
40
+
41
+ register_styles :default do
42
+ {
43
+ variants: {
44
+ body1: "text-base font-normal",
45
+ body2: "text-sm font-normal",
46
+ h1: "text-3xl font-bold",
47
+ h2: "text-2xl font-bold",
48
+ h3: "text-xl font-semibold",
49
+ h4: "text-lg font-semibold",
50
+ h5: "text-base font-semibold",
51
+ h6: "text-sm font-semibold"
52
+ },
53
+ colors: {
54
+ default: "text-default-700",
55
+ dark: "text-default-900",
56
+ muted: "text-default-500",
57
+ primary: "text-primary-600",
58
+ secondary: "text-secondary-600",
59
+ success: "text-success-600",
60
+ danger: "text-danger-600",
61
+ warning: "text-warning-600",
62
+ info: "text-info-600"
63
+ }
64
+ }
65
+ end
40
66
  end
41
67
  end
42
68
  end
@@ -0,0 +1,20 @@
1
+ module OkonomiUiKit
2
+ class Config
3
+ def self.register_styles(theme = :default, &block)
4
+ styles = block.call if block_given?
5
+
6
+ raise ArgumentError, "Styles must be a Hash" unless styles.is_a?(Hash)
7
+
8
+ styles_registry[theme] ||= {}
9
+ styles_registry[theme] = deep_merge({}, styles_registry[theme], styles)
10
+ end
11
+
12
+ def self.styles_registry
13
+ @styles_registry ||= {}
14
+ end
15
+
16
+ def self.deep_merge(*hashes)
17
+ OkonomiUiKit::TWMerge.deep_merge_all(*hashes)
18
+ end
19
+ end
20
+ end
@@ -85,7 +85,7 @@ module OkonomiUiKit
85
85
  ].compact.join(' ').split(' ').uniq
86
86
 
87
87
  select_html = super(method, choices, options, html_options.merge(class: css), &block)
88
- icon_html = @template.svg_icon(
88
+ icon_html = @template.ui.icon(
89
89
  ui.get_theme.dig(:components, :select, :icon, :file),
90
90
  class: ui.get_theme.dig(:components, :select, :icon, :class)
91
91
  )
@@ -108,7 +108,7 @@ module OkonomiUiKit
108
108
  ].compact.join(' ').split(' ').uniq
109
109
 
110
110
  select_html = super(method, collection, value_method, text_method, options, html_options.merge(class: css))
111
- icon_html = @template.svg_icon(
111
+ icon_html = @template.ui.icon(
112
112
  ui.get_theme.dig(:components, :select, :icon, :file),
113
113
  class: ui.get_theme.dig(:components, :select, :icon, :class)
114
114
  )
@@ -0,0 +1,108 @@
1
+ module OkonomiUiKit
2
+ class TWMerge
3
+ # ---- Public API -----------------------------------------------------------
4
+
5
+ # Merge two Tailwind class strings with conflict resolution.
6
+ def self.merge(a, b)
7
+ tokens = "#{a} #{b}".split(/\s+/).reject(&:empty?)
8
+ result = []
9
+ index_by_key = {}
10
+
11
+ tokens.each do |tok|
12
+ variants, base = split_variants(tok)
13
+ group = conflict_group_for(base)
14
+ key = [variants, group || "literal:#{base}"]
15
+
16
+ if index_by_key.key?(key)
17
+ pos = index_by_key[key]
18
+ result[pos] = tok
19
+ else
20
+ index_by_key[key] = result.length
21
+ result << tok
22
+ end
23
+ end
24
+
25
+ result.join(' ')
26
+ end
27
+
28
+ # Deep-merge two hashes; when both values are strings, merge as Tailwind classes.
29
+ # For other types, the right-hand value wins unless it is nil.
30
+ def self.deep_merge(a, b)
31
+ if a.is_a?(Hash) && b.is_a?(Hash)
32
+ (a.keys | b.keys).each_with_object({}) do |k, h|
33
+ h[k] = deep_merge(a[k], b[k])
34
+ end
35
+ elsif a.is_a?(String) && b.is_a?(String)
36
+ merge(a, b)
37
+ else
38
+ b.nil? ? a : b
39
+ end
40
+ end
41
+
42
+ def self.deep_merge_all(*hashes)
43
+ hashes.reduce({}) do |result, hash|
44
+ if hash.is_a?(Hash)
45
+ deep_merge(result, hash)
46
+ else
47
+ raise ArgumentError, "All arguments must be Hashes"
48
+ end
49
+ end
50
+ end
51
+
52
+ # ---- Implementation details ----------------------------------------------
53
+
54
+ # Conflict groups (minimal, extensible). More specific patterns first.
55
+ CONFLICT_RULES = [
56
+ # 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],
62
+
63
+ # 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],
66
+
67
+ # 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],
72
+
73
+ # 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],
78
+
79
+ # 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],
82
+
83
+ # Background
84
+ [/^bg-(?:inherit|current|transparent|black|white|[a-z]+-\d{2,3}|[a-z]+-950|\[.+\])$/, :bg_color],
85
+
86
+ # 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],
90
+ ].freeze
91
+
92
+ class << self
93
+ private
94
+
95
+ # "sm:hover:text-lg" -> ["sm:hover", "text-lg"]
96
+ def split_variants(token)
97
+ parts = token.split(':')
98
+ return ["", token] if parts.size == 1
99
+ [parts[0..-2].join(':'), parts[-1]]
100
+ end
101
+
102
+ def conflict_group_for(base)
103
+ rule = CONFLICT_RULES.find { |(rx, _)| base.match?(rx) }
104
+ rule ? rule[1] : nil
105
+ end
106
+ end
107
+ end
108
+ end
@@ -2,33 +2,10 @@ module OkonomiUiKit
2
2
  module Theme
3
3
  LIGHT_THEME = {
4
4
  components: {
5
- typography: {
6
- variants: {
7
- body1: "text-base font-normal",
8
- body2: "text-sm font-normal",
9
- h1: "text-3xl font-bold",
10
- h2: "text-2xl font-bold",
11
- h3: "text-xl font-semibold",
12
- h4: "text-lg font-semibold",
13
- h5: "text-base font-semibold",
14
- h6: "text-sm font-semibold"
15
- },
16
- colors: {
17
- default: "text-default-700",
18
- dark: "text-default-900",
19
- muted: "text-default-500",
20
- primary: "text-primary-600",
21
- secondary: "text-secondary-600",
22
- success: "text-success-600",
23
- danger: "text-danger-600",
24
- warning: "text-warning-600",
25
- info: "text-info-600"
26
- }
27
- },
28
5
  link: {
29
- root: "hover:cursor-pointer",
6
+ root: "hover:cursor-pointer text-sm",
30
7
  outlined: {
31
- root: "inline-flex border items-center justify-center px-4 py-2 font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
8
+ 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",
32
9
  colors: {
33
10
  default: "bg-white text-default-700 border-default-700 hover:bg-default-50",
34
11
  primary: "bg-white text-primary-600 border-primary-600 hover:bg-primary-50",
@@ -40,7 +17,7 @@ module OkonomiUiKit
40
17
  }
41
18
  },
42
19
  contained: {
43
- root: "inline-flex border items-center justify-center px-4 py-2 font-medium focus:outline-none focus:ring-2 focus:ring-offset-2",
20
+ 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",
44
21
  colors: {
45
22
  default: "border-default-700 bg-default-600 text-white hover:bg-default-700",
46
23
  primary: "border-primary-700 bg-primary-600 text-white hover:bg-primary-700",
@@ -26,42 +26,6 @@ module OkonomiUiKit
26
26
  @_okonomi_ui_kit_theme ||= OkonomiUiKit::Theme::DEFAULT_THEME
27
27
  end
28
28
 
29
- def link_to(name = nil, options = nil, html_options = nil, &block)
30
- html_options, options, name = options, name, block if block_given?
31
-
32
- html_options ||= {}
33
- html_options[:class] ||= ''
34
-
35
- variant = (html_options.delete(:variant) || 'text').to_sym
36
- color = (html_options.delete(:color) || 'default').to_sym
37
-
38
- html_options[:class] = button_class(variant:, color:, classes: html_options[:class])
39
-
40
- if block_given?
41
- @template.link_to(options, html_options, &block)
42
- else
43
- @template.link_to(name, options, html_options)
44
- end
45
- end
46
-
47
- def button_to(name = nil, options = nil, html_options = nil, &block)
48
- html_options, options, name = options, name, block if block_given?
49
-
50
- html_options ||= {}
51
- html_options[:class] ||= ''
52
-
53
- variant = (html_options.delete(:variant) || 'contained').to_sym
54
- color = (html_options.delete(:color) || 'default').to_sym
55
-
56
- html_options[:class] = button_class(variant:, color:, classes: html_options[:class])
57
-
58
- if block_given?
59
- @template.button_to(options, html_options, &block)
60
- else
61
- @template.button_to(name, options, html_options)
62
- end
63
- end
64
-
65
29
  def button_class(variant: 'contained', color: 'default', classes: '')
66
30
  [
67
31
  get_theme.dig(:components, :link, :root) || '',
@@ -71,10 +35,6 @@ module OkonomiUiKit
71
35
  ].join(' ')
72
36
  end
73
37
 
74
- def page(&block)
75
- @template.page(&block)
76
- end
77
-
78
38
  def confirmation_modal(title:, message:, confirm_text: "Confirm", cancel_text: "Cancel", variant: :warning, size: :md, **options, &block)
79
39
  modal_options = {
80
40
  title: title,
@@ -0,0 +1,46 @@
1
+ <%= tag.nav(**options.merge(class: component.style(:nav), 'aria-label': 'Breadcrumb')) do %>
2
+ <ol role="list" class="<%= component.style(:list) %>">
3
+ <% items.each_with_index do |item, index| %>
4
+ <li>
5
+ <div class="flex items-center">
6
+ <% if index == 0 %>
7
+ <% if item[:icon] %>
8
+ <% if item[:path] %>
9
+ <%= link_to item[:path], class: "text-gray-400 hover:text-gray-500", 'aria-current': (item[:current] ? 'page' : nil) do %>
10
+ <%= item[:icon] %>
11
+ <span class="sr-only"><%= item[:text] %></span>
12
+ <% end %>
13
+ <% else %>
14
+ <span class="text-gray-400" aria-current="<%= item[:current] ? 'page' : nil %>">
15
+ <%= item[:icon] %>
16
+ <span class="sr-only"><%= item[:text] %></span>
17
+ </span>
18
+ <% end %>
19
+ <% else %>
20
+ <div class="flex items-center">
21
+ <% if item[:path] && !item[:current] %>
22
+ <%= link_to item[:text], item[:path], class: component.style(:link, :first), 'aria-current': nil %>
23
+ <% else %>
24
+ <span class="<%= component.style(:link, :first) %>" aria-current="<%= item[:current] ? 'page' : nil %>">
25
+ <%= item[:text] %>
26
+ </span>
27
+ <% end %>
28
+ </div>
29
+ <% end %>
30
+ <% else %>
31
+ <svg class="<%= component.style(:separator, :base) %>" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
32
+ <path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
33
+ </svg>
34
+ <% if item[:path] && !item[:current] %>
35
+ <%= link_to item[:text], item[:path], class: component.style(:link, :base), 'aria-current': nil %>
36
+ <% else %>
37
+ <span class="<%= component.style(:link, :current) %>" aria-current="<%= item[:current] ? 'page' : nil %>">
38
+ <%= item[:text] %>
39
+ </span>
40
+ <% end %>
41
+ <% end %>
42
+ </div>
43
+ </li>
44
+ <% end %>
45
+ </ol>
46
+ <% end %>
@@ -0,0 +1 @@
1
+ <pre<%= language ? " data-language=\"#{language}\"".html_safe : "" %> class="<%= classes %>"<%= tag.attributes(options) %>><code><%= content %></code></pre>
@@ -0,0 +1,38 @@
1
+ <%
2
+ # Load the SVG content
3
+ svg_content = if OkonomiUiKit::SvgIcons.exist?(name)
4
+ OkonomiUiKit::SvgIcons.read(name)
5
+ else
6
+ "<!-- SVG #{name} not found -->"
7
+ end
8
+
9
+ # Parse and modify the SVG
10
+ if svg_content.start_with?("<!--")
11
+ %><%= raw svg_content %><%
12
+ else
13
+ doc = Nokogiri::HTML::DocumentFragment.parse(svg_content)
14
+ svg = doc.at_css('svg')
15
+
16
+ if svg
17
+ # Apply classes
18
+ svg['class'] = classes if classes.present?
19
+
20
+ # Apply dimensions
21
+ svg['width'] = width if width.present?
22
+ svg['height'] = height if height.present?
23
+
24
+ # Apply any additional options as attributes
25
+ options.each do |key, value|
26
+ if key.to_s == 'data' && value.is_a?(Hash)
27
+ # Handle data attributes specially
28
+ value.each do |data_key, data_value|
29
+ svg["data-#{data_key.to_s.dasherize}"] = data_value
30
+ end
31
+ else
32
+ svg[key.to_s.dasherize] = value
33
+ end
34
+ end
35
+ end
36
+ %><%= raw doc.to_html %><%
37
+ end
38
+ %>
@@ -0,0 +1,5 @@
1
+ <div class="flex flex-col gap-8 p-8 <%= options[:class] || '' %>">
2
+ <% content = capture { yield(builder) } %>
3
+ <%= builder.render_content %>
4
+ <%= content if builder.render_content.blank? %>
5
+ </div>
@@ -0,0 +1,3 @@
1
+ <table class="min-w-full divide-y divide-gray-300" <%= tag.attributes(options) %>>
2
+ <%= yield builder %>
3
+ </table>
@@ -11,10 +11,10 @@
11
11
  <% if blob.image? %>
12
12
  <%= image_tag url_for(blob), class: "max-h-32" %>
13
13
  <% else %>
14
- <%= svg_icon("heroicons/solid/document", class: "size-12 text-gray-400") %>
14
+ <%= ui.icon("heroicons/solid/document", class: "size-12 text-gray-400") %>
15
15
  <% end %>
16
16
  <% else %>
17
- <%= svg_icon("heroicons/solid/plus", class: "size-12 w-12 text-gray-400") %>
17
+ <%= ui.icon("heroicons/solid/plus", class: "size-12 w-12 text-gray-400") %>
18
18
  <% end %>
19
19
  </div>
20
20
 
@@ -28,7 +28,7 @@
28
28
  class="<%= ui.get_theme.dig(:components, :modal, :close_button, :button) %>"
29
29
  data-action="click->modal#close">
30
30
  <span class="sr-only">Close</span>
31
- <%= svg_icon(ui.get_theme.dig(:components, :modal, :close_button, :icon, :file),
31
+ <%= ui.icon(ui.get_theme.dig(:components, :modal, :close_button, :icon, :file),
32
32
  class: ui.get_theme.dig(:components, :modal, :close_button, :icon, :class)) %>
33
33
  </button>
34
34
  </div>
@@ -37,7 +37,7 @@
37
37
  <div class="<%= ui.get_theme.dig(:components, :modal, :content, :wrapper) %>">
38
38
  <!-- Icon -->
39
39
  <div class="<%= ui.modal_icon_wrapper_class(options[:variant]) %>">
40
- <%= svg_icon(ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :file),
40
+ <%= ui.icon(ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :file),
41
41
  class: [ui.get_theme.dig(:components, :modal, :icon, :class),
42
42
  ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :icon)].join(' ')) %>
43
43
  </div>
@@ -9,7 +9,7 @@
9
9
  <% if defined?(initials) && initials.present? %>
10
10
  <span class="flex size-6 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-[0.625rem] font-medium text-gray-400 group-hover:border-primary-600 group-hover:text-primary-600"><%= initials %></span>
11
11
  <% elsif defined?(icon) && icon.present? %>
12
- <%= svg_icon icon, class: "size-6 text-gray-400 group-hover:text-primary-600" %>
12
+ <%= ui.icon icon, class: "size-6 text-gray-400 group-hover:text-primary-600" %>
13
13
  <% end %>
14
14
  <%= title %>
15
15
  <% end %>
@@ -22,12 +22,7 @@ module OkonomiUiKit
22
22
  ActiveSupport.on_load(:action_view) do
23
23
  include OkonomiUiKit::ApplicationHelper
24
24
  include OkonomiUiKit::AttributeSectionHelper
25
- include OkonomiUiKit::BadgeHelper
26
- include OkonomiUiKit::BreadcrumbsHelper
27
- include OkonomiUiKit::IconHelper
28
25
  include OkonomiUiKit::NavigationHelper
29
- include OkonomiUiKit::PageBuilderHelper
30
- include OkonomiUiKit::TableHelper
31
26
  include OkonomiUiKit::UiHelper
32
27
 
33
28
  ActionView::Base.field_error_proc = ->(html_tag, _instance) { html_tag.html_safe }
@@ -1,3 +1,3 @@
1
1
  module OkonomiUiKit
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.8"
3
3
  end