okonomi_ui_kit 0.1.5 → 0.1.7
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/app/assets/builds/okonomi_ui_kit/application.tailwind.css +313 -4
- data/app/helpers/okonomi_ui_kit/component.rb +80 -0
- data/app/helpers/okonomi_ui_kit/components/alert.rb +9 -0
- data/app/helpers/okonomi_ui_kit/components/badge.rb +31 -0
- data/app/helpers/okonomi_ui_kit/components/button_to.rb +34 -0
- data/app/helpers/okonomi_ui_kit/components/code.rb +73 -0
- data/app/helpers/okonomi_ui_kit/components/link_to.rb +34 -0
- data/app/helpers/okonomi_ui_kit/components/page.rb +247 -0
- data/app/helpers/okonomi_ui_kit/components/table.rb +207 -0
- data/app/helpers/okonomi_ui_kit/components/typography.rb +68 -0
- data/app/helpers/okonomi_ui_kit/config.rb +16 -0
- data/app/helpers/okonomi_ui_kit/theme.rb +55 -3
- data/app/helpers/okonomi_ui_kit/ui_helper.rb +35 -63
- data/app/javascript/okonomi_ui_kit/controllers/modal_controller.js +94 -0
- data/app/views/okonomi/components/alert/_alert.html.erb +3 -0
- data/app/views/okonomi/components/code/_code.html.erb +1 -0
- data/app/views/okonomi/components/page/_page.html.erb +5 -0
- data/app/views/okonomi/components/table/_table.html.erb +3 -0
- data/app/views/okonomi/components/typography/_typography.html.erb +7 -0
- data/app/views/okonomi/modals/_confirmation_modal.html.erb +77 -0
- data/lib/okonomi_ui_kit/engine.rb +0 -3
- data/lib/okonomi_ui_kit/version.rb +1 -1
- metadata +23 -7
- data/app/helpers/okonomi_ui_kit/badge_helper.rb +0 -23
- data/app/helpers/okonomi_ui_kit/page_builder_helper.rb +0 -217
- data/app/helpers/okonomi_ui_kit/table_helper.rb +0 -158
- data/app/views/okonomi/components/_typography.html.erb +0 -7
@@ -0,0 +1,77 @@
|
|
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
|
+
<%= ui.modal_data_attributes(options) %>>
|
8
|
+
|
9
|
+
<!-- Backdrop -->
|
10
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :backdrop) %>"
|
11
|
+
data-modal-target="backdrop"
|
12
|
+
data-action="click->modal#close"
|
13
|
+
aria-hidden="true"></div>
|
14
|
+
|
15
|
+
<!-- Modal container -->
|
16
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :container) %>">
|
17
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :wrapper) %>">
|
18
|
+
<!-- Modal panel -->
|
19
|
+
<div class="<%= ui.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="<%= ui.get_theme.dig(:components, :modal, :close_button, :wrapper) %>">
|
27
|
+
<button type="button"
|
28
|
+
class="<%= ui.get_theme.dig(:components, :modal, :close_button, :button) %>"
|
29
|
+
data-action="click->modal#close">
|
30
|
+
<span class="sr-only">Close</span>
|
31
|
+
<%= svg_icon(ui.get_theme.dig(:components, :modal, :close_button, :icon, :file),
|
32
|
+
class: ui.get_theme.dig(:components, :modal, :close_button, :icon, :class)) %>
|
33
|
+
</button>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<!-- Content -->
|
37
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :content, :wrapper) %>">
|
38
|
+
<!-- Icon -->
|
39
|
+
<div class="<%= ui.modal_icon_wrapper_class(options[:variant]) %>">
|
40
|
+
<%= svg_icon(ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :file),
|
41
|
+
class: [ui.get_theme.dig(:components, :modal, :icon, :class),
|
42
|
+
ui.get_theme.dig(:components, :modal, :icon, :variants, options[:variant], :icon)].join(' ')) %>
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<!-- Text content -->
|
46
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :content, :text_wrapper) %>">
|
47
|
+
<h3 id="modal-title" class="<%= ui.get_theme.dig(:components, :modal, :content, :title) %>">
|
48
|
+
<%= options[:title] %>
|
49
|
+
</h3>
|
50
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :content, :message) %>">
|
51
|
+
<p><%= options[:message] %></p>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
|
56
|
+
<!-- Actions -->
|
57
|
+
<div class="<%= ui.get_theme.dig(:components, :modal, :actions, :wrapper) %>">
|
58
|
+
<% if options[:has_custom_actions] %>
|
59
|
+
<%= yield %>
|
60
|
+
<% else %>
|
61
|
+
<% button_color = options[:variant] == :warning ? :danger : options[:variant] %>
|
62
|
+
<button type="button"
|
63
|
+
class="<%= ui.button_class(variant: :contained, color: button_color) %> sm:ml-3 sm:w-auto"
|
64
|
+
data-action="click->modal#confirm">
|
65
|
+
<%= options[:confirm_text] %>
|
66
|
+
</button>
|
67
|
+
<button type="button"
|
68
|
+
class="<%= ui.button_class(variant: :outlined, color: :default) %> mt-3 sm:mt-0 sm:w-auto"
|
69
|
+
data-action="click->modal#close">
|
70
|
+
<%= options[:cancel_text] %>
|
71
|
+
</button>
|
72
|
+
<% end %>
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
</div>
|
@@ -22,12 +22,9 @@ 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
25
|
include OkonomiUiKit::BreadcrumbsHelper
|
27
26
|
include OkonomiUiKit::IconHelper
|
28
27
|
include OkonomiUiKit::NavigationHelper
|
29
|
-
include OkonomiUiKit::PageBuilderHelper
|
30
|
-
include OkonomiUiKit::TableHelper
|
31
28
|
include OkonomiUiKit::UiHelper
|
32
29
|
|
33
30
|
ActionView::Base.field_error_proc = ->(html_tag, _instance) { html_tag.html_safe }
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: okonomi_ui_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Okonomi GmbH
|
8
|
+
autorequire:
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date:
|
11
|
+
date: 2025-08-01 00:00:00.000000000 Z
|
11
12
|
dependencies:
|
12
13
|
- !ruby/object:Gem::Dependency
|
13
14
|
name: rails
|
@@ -1356,14 +1357,21 @@ files:
|
|
1356
1357
|
- app/controllers/okonomi_ui_kit/application_controller.rb
|
1357
1358
|
- app/helpers/okonomi_ui_kit/application_helper.rb
|
1358
1359
|
- app/helpers/okonomi_ui_kit/attribute_section_helper.rb
|
1359
|
-
- app/helpers/okonomi_ui_kit/badge_helper.rb
|
1360
1360
|
- app/helpers/okonomi_ui_kit/breadcrumbs_helper.rb
|
1361
|
+
- app/helpers/okonomi_ui_kit/component.rb
|
1362
|
+
- app/helpers/okonomi_ui_kit/components/alert.rb
|
1363
|
+
- app/helpers/okonomi_ui_kit/components/badge.rb
|
1364
|
+
- app/helpers/okonomi_ui_kit/components/button_to.rb
|
1365
|
+
- app/helpers/okonomi_ui_kit/components/code.rb
|
1366
|
+
- app/helpers/okonomi_ui_kit/components/link_to.rb
|
1367
|
+
- app/helpers/okonomi_ui_kit/components/page.rb
|
1368
|
+
- app/helpers/okonomi_ui_kit/components/table.rb
|
1369
|
+
- app/helpers/okonomi_ui_kit/components/typography.rb
|
1370
|
+
- app/helpers/okonomi_ui_kit/config.rb
|
1361
1371
|
- app/helpers/okonomi_ui_kit/form_builder.rb
|
1362
1372
|
- app/helpers/okonomi_ui_kit/icon_helper.rb
|
1363
1373
|
- app/helpers/okonomi_ui_kit/navigation_helper.rb
|
1364
|
-
- app/helpers/okonomi_ui_kit/page_builder_helper.rb
|
1365
1374
|
- app/helpers/okonomi_ui_kit/svg_icons.rb
|
1366
|
-
- app/helpers/okonomi_ui_kit/table_helper.rb
|
1367
1375
|
- app/helpers/okonomi_ui_kit/theme.rb
|
1368
1376
|
- app/helpers/okonomi_ui_kit/theme_helper.rb
|
1369
1377
|
- app/helpers/okonomi_ui_kit/ui_helper.rb
|
@@ -1372,6 +1380,7 @@ files:
|
|
1372
1380
|
- app/javascript/okonomi_ui_kit/controllers/file_input_controller.js
|
1373
1381
|
- app/javascript/okonomi_ui_kit/controllers/flash_controller.js
|
1374
1382
|
- app/javascript/okonomi_ui_kit/controllers/form_field_visibility_controller.js
|
1383
|
+
- app/javascript/okonomi_ui_kit/controllers/modal_controller.js
|
1375
1384
|
- app/javascript/okonomi_ui_kit/controllers/upload_controller.js
|
1376
1385
|
- app/javascript/okonomi_ui_kit_manifest.js
|
1377
1386
|
- app/jobs/okonomi_ui_kit/application_job.rb
|
@@ -1379,13 +1388,18 @@ files:
|
|
1379
1388
|
- app/models/okonomi_ui_kit/application_record.rb
|
1380
1389
|
- app/views/layouts/okonomi_ui_kit/application.html.erb
|
1381
1390
|
- app/views/okonomi/attribute_sections/_section.html.erb
|
1382
|
-
- app/views/okonomi/components/
|
1391
|
+
- app/views/okonomi/components/alert/_alert.html.erb
|
1392
|
+
- app/views/okonomi/components/code/_code.html.erb
|
1393
|
+
- app/views/okonomi/components/page/_page.html.erb
|
1394
|
+
- app/views/okonomi/components/table/_table.html.erb
|
1395
|
+
- app/views/okonomi/components/typography/_typography.html.erb
|
1383
1396
|
- app/views/okonomi/forms/tailwind/_checkbox_label.html.erb
|
1384
1397
|
- app/views/okonomi/forms/tailwind/_field.html.erb
|
1385
1398
|
- app/views/okonomi/forms/tailwind/_field_set.html.erb
|
1386
1399
|
- app/views/okonomi/forms/tailwind/_multi_select.html.erb
|
1387
1400
|
- app/views/okonomi/forms/tailwind/_radio_button.html.erb
|
1388
1401
|
- app/views/okonomi/forms/tailwind/_upload_field.html.erb
|
1402
|
+
- app/views/okonomi/modals/_confirmation_modal.html.erb
|
1389
1403
|
- app/views/okonomi/navigation/_link.html.erb
|
1390
1404
|
- app/views/okonomi/navigation/_menu.html.erb
|
1391
1405
|
- app/views/okonomi/navigation/_navbar.html.erb
|
@@ -1405,6 +1419,7 @@ metadata:
|
|
1405
1419
|
homepage_uri: https://okonomi.gmbh
|
1406
1420
|
source_code_uri: https://okonomi.gmbh
|
1407
1421
|
changelog_uri: https://okonomi.gmbh
|
1422
|
+
post_install_message:
|
1408
1423
|
rdoc_options: []
|
1409
1424
|
require_paths:
|
1410
1425
|
- lib
|
@@ -1419,7 +1434,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1419
1434
|
- !ruby/object:Gem::Version
|
1420
1435
|
version: '0'
|
1421
1436
|
requirements: []
|
1422
|
-
rubygems_version: 3.
|
1437
|
+
rubygems_version: 3.4.10
|
1438
|
+
signing_key:
|
1423
1439
|
specification_version: 4
|
1424
1440
|
summary: UI Kit for Okonomi applications
|
1425
1441
|
test_files: []
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module OkonomiUiKit
|
2
|
-
module BadgeHelper
|
3
|
-
def badge(text, severity = :default, **options)
|
4
|
-
color_classes = case severity.to_sym
|
5
|
-
when :success
|
6
|
-
"bg-green-100 text-green-800"
|
7
|
-
when :danger
|
8
|
-
"bg-red-100 text-red-800"
|
9
|
-
when :info
|
10
|
-
"bg-blue-100 text-blue-800"
|
11
|
-
when :warning
|
12
|
-
"bg-yellow-100 text-yellow-800"
|
13
|
-
else
|
14
|
-
"bg-gray-100 text-gray-800"
|
15
|
-
end
|
16
|
-
|
17
|
-
base_classes = "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"
|
18
|
-
full_classes = "#{base_classes} #{color_classes} #{options[:class] || ''}".strip
|
19
|
-
|
20
|
-
tag.span(text, class: full_classes, **options.except(:class))
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,217 +0,0 @@
|
|
1
|
-
module OkonomiUiKit
|
2
|
-
module PageBuilderHelper
|
3
|
-
def page(**options, &block)
|
4
|
-
builder = PageBuilder.new(self)
|
5
|
-
|
6
|
-
render 'okonomi/page_builder/page', builder: builder, options: options, &block
|
7
|
-
end
|
8
|
-
|
9
|
-
class PageBuilder
|
10
|
-
include ActionView::Helpers::TagHelper
|
11
|
-
include ActionView::Helpers::CaptureHelper
|
12
|
-
|
13
|
-
def initialize(template)
|
14
|
-
@template = template
|
15
|
-
end
|
16
|
-
|
17
|
-
def page_header(**options, &block)
|
18
|
-
header_builder = PageHeaderBuilder.new(@template)
|
19
|
-
yield(header_builder) if block_given?
|
20
|
-
header_builder.render
|
21
|
-
end
|
22
|
-
|
23
|
-
def section(**options, &block)
|
24
|
-
section_builder = SectionBuilder.new(@template)
|
25
|
-
yield(section_builder) if block_given?
|
26
|
-
section_builder.render
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def tag
|
32
|
-
@template.tag
|
33
|
-
end
|
34
|
-
|
35
|
-
def capture(*args, &block)
|
36
|
-
@template.capture(*args, &block)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class PageHeaderBuilder
|
41
|
-
include ActionView::Helpers::TagHelper
|
42
|
-
include ActionView::Helpers::CaptureHelper
|
43
|
-
|
44
|
-
def initialize(template)
|
45
|
-
@template = template
|
46
|
-
@breadcrumbs_content = nil
|
47
|
-
@row_content = nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def breadcrumbs(&block)
|
51
|
-
@breadcrumbs_content = @template.breadcrumbs(&block)
|
52
|
-
end
|
53
|
-
|
54
|
-
def row(&block)
|
55
|
-
row_builder = PageHeaderRowBuilder.new(@template)
|
56
|
-
yield(row_builder) if block_given?
|
57
|
-
@row_content = row_builder.render
|
58
|
-
end
|
59
|
-
|
60
|
-
def render
|
61
|
-
content = []
|
62
|
-
content << @breadcrumbs_content if @breadcrumbs_content
|
63
|
-
content << @row_content if @row_content
|
64
|
-
|
65
|
-
tag.div(class: "flex flex-col gap-2") do
|
66
|
-
@template.safe_join(content.compact)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def tag
|
73
|
-
@template.tag
|
74
|
-
end
|
75
|
-
|
76
|
-
def capture(*args, &block)
|
77
|
-
@template.capture(*args, &block)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class PageHeaderRowBuilder
|
82
|
-
include ActionView::Helpers::TagHelper
|
83
|
-
include ActionView::Helpers::CaptureHelper
|
84
|
-
|
85
|
-
def initialize(template)
|
86
|
-
@template = template
|
87
|
-
@title_content = nil
|
88
|
-
@actions_content = nil
|
89
|
-
end
|
90
|
-
|
91
|
-
def title(text, **options)
|
92
|
-
@title_content = tag.h1(text, class: "text-2xl font-bold leading-7 text-gray-900 truncate sm:text-3xl sm:tracking-tight")
|
93
|
-
end
|
94
|
-
|
95
|
-
def actions(&block)
|
96
|
-
@actions_content = tag.div(class: "mt-4 flex md:ml-4 md:mt-0 gap-2") do
|
97
|
-
capture(&block) if block_given?
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def render
|
102
|
-
tag.div(class: "flex w-full justify-between items-center") do
|
103
|
-
content = []
|
104
|
-
content << @title_content if @title_content
|
105
|
-
content << @actions_content if @actions_content
|
106
|
-
@template.safe_join(content.compact)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
private
|
111
|
-
|
112
|
-
def tag
|
113
|
-
@template.tag
|
114
|
-
end
|
115
|
-
|
116
|
-
def capture(*args, &block)
|
117
|
-
@template.capture(*args, &block)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class SectionBuilder
|
122
|
-
include ActionView::Helpers::TagHelper
|
123
|
-
include ActionView::Helpers::CaptureHelper
|
124
|
-
|
125
|
-
def initialize(template)
|
126
|
-
@template = template
|
127
|
-
@title_content = nil
|
128
|
-
@subtitle_content = nil
|
129
|
-
@actions_content = nil
|
130
|
-
@body_content = nil
|
131
|
-
end
|
132
|
-
|
133
|
-
def title(text, **options)
|
134
|
-
@title_content = tag.h3(text, class: "text-base/7 font-semibold text-gray-900")
|
135
|
-
end
|
136
|
-
|
137
|
-
def subtitle(text, **options)
|
138
|
-
@subtitle_content = tag.p(text, class: "mt-1 max-w-2xl text-sm/6 text-gray-500")
|
139
|
-
end
|
140
|
-
|
141
|
-
def actions(&block)
|
142
|
-
@actions_content = tag.div(class: "mt-4 flex md:ml-4 md:mt-0") do
|
143
|
-
capture(&block) if block_given?
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def body(&block)
|
148
|
-
@body_content = tag.div do
|
149
|
-
tag.dl(class: "divide-y divide-gray-100") do
|
150
|
-
capture(&block) if block_given?
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def attribute(label, value = nil, **options, &block)
|
156
|
-
content = if block_given?
|
157
|
-
capture(&block)
|
158
|
-
elsif value.respond_to?(:call)
|
159
|
-
value.call
|
160
|
-
else
|
161
|
-
value
|
162
|
-
end
|
163
|
-
|
164
|
-
tag.div(class: "py-6 sm:grid sm:grid-cols-3 sm:gap-4") do
|
165
|
-
dt_content = tag.dt(label, class: "text-sm font-medium text-gray-900")
|
166
|
-
dd_content = tag.dd(content, class: "mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0")
|
167
|
-
|
168
|
-
dt_content + dd_content
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def render
|
173
|
-
tag.div(class: "overflow-hidden bg-white") do
|
174
|
-
header_content = build_header
|
175
|
-
content_parts = []
|
176
|
-
content_parts << header_content if header_content.present?
|
177
|
-
content_parts << @body_content if @body_content
|
178
|
-
@template.safe_join(content_parts.compact)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
private
|
183
|
-
|
184
|
-
def build_header
|
185
|
-
return nil unless @title_content || @subtitle_content || @actions_content
|
186
|
-
|
187
|
-
tag.div(class: "py-6") do
|
188
|
-
if @actions_content
|
189
|
-
tag.div(class: "flex w-full justify-between items-start") do
|
190
|
-
title_section = tag.div do
|
191
|
-
content_parts = []
|
192
|
-
content_parts << @title_content if @title_content
|
193
|
-
content_parts << @subtitle_content if @subtitle_content
|
194
|
-
@template.safe_join(content_parts.compact)
|
195
|
-
end
|
196
|
-
|
197
|
-
title_section + @actions_content
|
198
|
-
end
|
199
|
-
else
|
200
|
-
content_parts = []
|
201
|
-
content_parts << @title_content if @title_content
|
202
|
-
content_parts << @subtitle_content if @subtitle_content
|
203
|
-
@template.safe_join(content_parts.compact)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def tag
|
209
|
-
@template.tag
|
210
|
-
end
|
211
|
-
|
212
|
-
def capture(*args, &block)
|
213
|
-
@template.capture(*args, &block)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
@@ -1,158 +0,0 @@
|
|
1
|
-
module OkonomiUiKit
|
2
|
-
module TableHelper
|
3
|
-
def table(**options, &block)
|
4
|
-
builder = TableBuilder.new(self)
|
5
|
-
|
6
|
-
render 'okonomi/tables/table', builder: builder, options: options, &block
|
7
|
-
end
|
8
|
-
|
9
|
-
class TableBuilder
|
10
|
-
include ActionView::Helpers::TagHelper
|
11
|
-
include ActionView::Helpers::CaptureHelper
|
12
|
-
|
13
|
-
def initialize(template)
|
14
|
-
@template = template
|
15
|
-
@current_row_cells = []
|
16
|
-
@in_header = false
|
17
|
-
@in_body = false
|
18
|
-
end
|
19
|
-
|
20
|
-
def head(&block)
|
21
|
-
@in_header = true
|
22
|
-
@in_body = false
|
23
|
-
result = tag.thead(&block)
|
24
|
-
@in_header = false
|
25
|
-
result
|
26
|
-
end
|
27
|
-
|
28
|
-
def body(&block)
|
29
|
-
@in_header = false
|
30
|
-
@in_body = true
|
31
|
-
result = tag.tbody(class: "divide-y divide-gray-200 bg-white", &block)
|
32
|
-
@in_body = false
|
33
|
-
result
|
34
|
-
end
|
35
|
-
|
36
|
-
def tr(&block)
|
37
|
-
@current_row_cells = []
|
38
|
-
|
39
|
-
# Collect all cells first
|
40
|
-
yield if block_given?
|
41
|
-
|
42
|
-
# Now render each cell with proper first/last detection
|
43
|
-
rendered_cells = @current_row_cells.map.with_index do |cell, index|
|
44
|
-
is_first = index == 0
|
45
|
-
is_last = index == @current_row_cells.length - 1
|
46
|
-
|
47
|
-
if cell[:type] == :th
|
48
|
-
render_th(cell, is_first, is_last)
|
49
|
-
else
|
50
|
-
render_td(cell, is_first, is_last)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
result = tag.tr do
|
55
|
-
@template.safe_join(rendered_cells)
|
56
|
-
end
|
57
|
-
|
58
|
-
@current_row_cells = []
|
59
|
-
result
|
60
|
-
end
|
61
|
-
|
62
|
-
def th(scope: "col", align: :left, **options, &block)
|
63
|
-
content = capture(&block) if block_given?
|
64
|
-
|
65
|
-
# Store cell data for later processing in tr
|
66
|
-
cell = { type: :th, scope: scope, align: align, options: options, content: content }
|
67
|
-
@current_row_cells << cell
|
68
|
-
|
69
|
-
# Return empty string for now, actual rendering happens in tr
|
70
|
-
""
|
71
|
-
end
|
72
|
-
|
73
|
-
def td(align: :left, **options, &block)
|
74
|
-
content = capture(&block) if block_given?
|
75
|
-
|
76
|
-
# Store cell data for later processing in tr
|
77
|
-
cell = { type: :td, align: align, options: options, content: content }
|
78
|
-
@current_row_cells << cell
|
79
|
-
|
80
|
-
# Return empty string for now, actual rendering happens in tr
|
81
|
-
""
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
def empty_state(title: "No records found", icon: "heroicons/outline/document", colspan: nil, &block)
|
86
|
-
content = if block_given?
|
87
|
-
capture(&block)
|
88
|
-
else
|
89
|
-
tag.div(class: "text-center py-8") do
|
90
|
-
icon_content = @template.svg_icon(icon, class: "mx-auto h-12 w-12 text-gray-400")
|
91
|
-
|
92
|
-
icon_content + tag.p(title, class: "mt-2 text-sm font-medium text-gray-900") +
|
93
|
-
tag.p("Get started by creating a new record.", class: "mt-1 text-sm text-gray-500")
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
tr do
|
98
|
-
td(colspan: colspan, class: "text-center py-8 text-gray-500") do
|
99
|
-
content
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def tag
|
107
|
-
@template.tag
|
108
|
-
end
|
109
|
-
|
110
|
-
def capture(*args, &block)
|
111
|
-
@template.capture(*args, &block)
|
112
|
-
end
|
113
|
-
|
114
|
-
def render_th(cell, is_first, is_last)
|
115
|
-
align_class = alignment_class(cell[:align])
|
116
|
-
|
117
|
-
if is_first
|
118
|
-
full_class = "py-3.5 pr-3 #{align_class} text-sm font-semibold text-gray-900 #{cell[:options][:class] || ""}".strip
|
119
|
-
elsif is_last
|
120
|
-
full_class = "relative py-3.5 #{align_class} text-sm font-semibold text-gray-900 #{cell[:options][:class] || ""}".strip
|
121
|
-
else
|
122
|
-
full_class = "pl-3 pr-3 py-3.5 #{align_class} text-sm font-semibold text-gray-900 #{cell[:options][:class] || ""}".strip
|
123
|
-
end
|
124
|
-
|
125
|
-
options = cell[:options].except(:class)
|
126
|
-
tag.th(cell[:content], scope: cell[:scope], class: full_class, **options)
|
127
|
-
end
|
128
|
-
|
129
|
-
def render_td(cell, is_first, is_last)
|
130
|
-
align_class = alignment_class(cell[:align])
|
131
|
-
|
132
|
-
if is_first
|
133
|
-
full_class = "py-4 pr-3 #{align_class} text-sm font-medium whitespace-nowrap text-gray-900 #{cell[:options][:class] || ""}".strip
|
134
|
-
elsif is_last
|
135
|
-
full_class = "relative py-4 #{align_class} text-sm font-medium whitespace-nowrap #{cell[:options][:class] || ""}".strip
|
136
|
-
else
|
137
|
-
full_class = "pl-3 pr-3 py-4 #{align_class} text-sm whitespace-nowrap text-gray-500 #{cell[:options][:class] || ""}".strip
|
138
|
-
end
|
139
|
-
|
140
|
-
options = cell[:options].except(:class)
|
141
|
-
tag.td(cell[:content], class: full_class, **options)
|
142
|
-
end
|
143
|
-
|
144
|
-
def alignment_class(align)
|
145
|
-
case align.to_sym
|
146
|
-
when :left
|
147
|
-
"text-left"
|
148
|
-
when :center
|
149
|
-
"text-center"
|
150
|
-
when :right
|
151
|
-
"text-right"
|
152
|
-
else
|
153
|
-
"text-left"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|