basecoat 0.1.1

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/.gitignore +8 -0
  3. data/.idea/basecoat.iml +17 -0
  4. data/.idea/misc.xml +4 -0
  5. data/.idea/modules.xml +8 -0
  6. data/.idea/vcs.xml +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +194 -0
  9. data/Rakefile +4 -0
  10. data/lib/basecoat/railtie.rb +11 -0
  11. data/lib/basecoat/version.rb +5 -0
  12. data/lib/basecoat.rb +8 -0
  13. data/lib/generators/basecoat/templates/application.html.erb +16 -0
  14. data/lib/generators/basecoat/templates/devise/confirmations/new.html.erb +27 -0
  15. data/lib/generators/basecoat/templates/devise/mailer/confirmation_instructions.html.erb +5 -0
  16. data/lib/generators/basecoat/templates/devise/mailer/email_changed.html.erb +7 -0
  17. data/lib/generators/basecoat/templates/devise/mailer/password_change.html.erb +3 -0
  18. data/lib/generators/basecoat/templates/devise/mailer/reset_password_instructions.html.erb +8 -0
  19. data/lib/generators/basecoat/templates/devise/mailer/unlock_instructions.html.erb +7 -0
  20. data/lib/generators/basecoat/templates/devise/passwords/edit.html.erb +40 -0
  21. data/lib/generators/basecoat/templates/devise/passwords/new.html.erb +31 -0
  22. data/lib/generators/basecoat/templates/devise/registrations/edit.html.erb +63 -0
  23. data/lib/generators/basecoat/templates/devise/registrations/new.html.erb +40 -0
  24. data/lib/generators/basecoat/templates/devise/sessions/new.html.erb +38 -0
  25. data/lib/generators/basecoat/templates/devise/shared/_error_messages.html.erb +15 -0
  26. data/lib/generators/basecoat/templates/devise/shared/_links.html.erb +27 -0
  27. data/lib/generators/basecoat/templates/devise/unlocks/new.html.erb +29 -0
  28. data/lib/generators/basecoat/templates/devise.html.erb +36 -0
  29. data/lib/generators/basecoat/templates/layouts/_alert.html.erb +6 -0
  30. data/lib/generators/basecoat/templates/layouts/_aside.html.erb +21 -0
  31. data/lib/generators/basecoat/templates/layouts/_form_errors.html.erb +13 -0
  32. data/lib/generators/basecoat/templates/layouts/_head.html.erb +21 -0
  33. data/lib/generators/basecoat/templates/layouts/_header.html.erb +12 -0
  34. data/lib/generators/basecoat/templates/layouts/_notice.html.erb +18 -0
  35. data/lib/generators/basecoat/templates/pagy.scss +31 -0
  36. data/lib/generators/basecoat/templates/passwords/edit.html.erb +30 -0
  37. data/lib/generators/basecoat/templates/passwords/new.html.erb +25 -0
  38. data/lib/generators/basecoat/templates/scaffold_hook.rb +36 -0
  39. data/lib/generators/basecoat/templates/sessions/new.html.erb +30 -0
  40. data/lib/generators/basecoat/templates/sessions.html.erb +36 -0
  41. data/lib/tasks/basecoat.rake +281 -0
  42. data/lib/templates/erb/scaffold/_form.html.erb.tt +43 -0
  43. data/lib/templates/erb/scaffold/edit.html.erb.tt +21 -0
  44. data/lib/templates/erb/scaffold/index.html.erb.tt +35 -0
  45. data/lib/templates/erb/scaffold/new.html.erb.tt +20 -0
  46. data/lib/templates/erb/scaffold/partial.html.erb.tt +20 -0
  47. data/lib/templates/erb/scaffold/show.html.erb.tt +23 -0
  48. data/sig/basecoat.rbs +4 -0
  49. metadata +104 -0
@@ -0,0 +1,281 @@
1
+ require 'fileutils'
2
+
3
+ namespace :basecoat do
4
+ desc "Install Basecoat application layout and partials"
5
+ task :install do
6
+ # Install basecoat-css (always install via yarn/npm for CSS)
7
+ puts "\n📦 Installing basecoat-css..."
8
+ system("yarn add basecoat-css") || system("npm install basecoat-css")
9
+ puts " Installed: basecoat-css via yarn/npm"
10
+
11
+ # If using importmap, also add to importmap.rb for JS
12
+ if File.exist?(Rails.root.join("config/importmap.rb"))
13
+ importmap_path = Rails.root.join("config/importmap.rb")
14
+ importmap_content = File.read(importmap_path)
15
+ unless importmap_content.include?("basecoat-css")
16
+ File.open(importmap_path, "a") do |f|
17
+ f.puts "\npin \"basecoat-css/all\", to: \"https://cdn.jsdelivr.net/npm/basecoat-css@0.3.2/dist/js/all.js\""
18
+ end
19
+ puts " Added: basecoat-css to config/importmap.rb"
20
+ end
21
+ end
22
+
23
+ # Add JavaScript imports and code
24
+ js_path = Rails.root.join("app/javascript/application.js")
25
+ if File.exist?(js_path)
26
+ js_content = File.read(js_path)
27
+
28
+ unless js_content.include?("basecoat-css")
29
+ # Add import after the last import line
30
+ js_content = js_content.sub(/(import\s+.*\n)(?!import)/, "\\1import \"basecoat-css/all\"\n")
31
+ File.write(js_path, js_content)
32
+ puts " Added: basecoat-css import to app/javascript/application.js"
33
+ end
34
+
35
+ # Add view transitions code
36
+ unless js_content.include?("turbo:before-frame-render")
37
+ view_transition_code = <<~JS
38
+
39
+ // View transitions for turbo frame navigation
40
+ addEventListener("turbo:before-frame-render", (event) => {
41
+ if (document.startViewTransition) {
42
+ const originalRender = event.detail.render
43
+ event.detail.render = async (currentElement, newElement) => {
44
+ const transition = document.startViewTransition(() => originalRender(currentElement, newElement))
45
+ await transition.finished
46
+ }
47
+ }
48
+ })
49
+ JS
50
+ File.open(js_path, "a") { |f| f.write(view_transition_code) }
51
+ puts " Added: View transitions to app/javascript/application.js"
52
+ end
53
+
54
+ # Add dark mode toggle code
55
+ unless js_content.include?("basecoat:theme")
56
+ dark_mode_code = <<~JS
57
+
58
+ // Dark mode toggle
59
+ const apply = dark => {
60
+ document.documentElement.classList.toggle('dark', dark);
61
+ try { localStorage.setItem('themeMode', dark ? 'dark' : 'light'); } catch (_) {}
62
+ };
63
+
64
+ // Apply theme on initial load (runs immediately to prevent flash)
65
+ try {
66
+ const stored = localStorage.getItem('themeMode');
67
+ if (stored ? stored === 'dark'
68
+ : matchMedia('(prefers-color-scheme: dark)').matches) {
69
+ document.documentElement.classList.add('dark');
70
+ }
71
+ } catch (_) {}
72
+
73
+ // Set up theme toggle event listener
74
+ document.addEventListener('basecoat:theme', (event) => {
75
+ const mode = event.detail?.mode;
76
+ apply(mode === 'dark' ? true
77
+ : mode === 'light' ? false
78
+ : !document.documentElement.classList.contains('dark'));
79
+ })
80
+ JS
81
+ File.open(js_path, "a") { |f| f.write(dark_mode_code) }
82
+ puts " Added: Dark mode toggle to app/javascript/application.js"
83
+ end
84
+ end
85
+
86
+ # Add CSS imports and styles
87
+ # Check for Tailwind v4 setup first
88
+ if File.exist?(Rails.root.join("app/assets/tailwind/application.css"))
89
+ tailwind_css = Rails.root.join("app/assets/tailwind/application.css")
90
+ content = File.read(tailwind_css)
91
+
92
+ # Add basecoat-css import if not present
93
+ unless content.include?("basecoat-css")
94
+ # Add after tailwindcss import
95
+ updated_content = content.sub(/(@import "tailwindcss";)/, "\\1\n@import \"basecoat-css\";")
96
+ File.write(tailwind_css, updated_content)
97
+ puts " Added: basecoat-css import to app/assets/tailwind/application.css"
98
+ end
99
+ else
100
+ # Traditional setup with app/assets/stylesheets
101
+ css_path = Rails.root.join("app/assets/stylesheets/application.css")
102
+ if File.exist?(css_path)
103
+ css_content = File.read(css_path)
104
+
105
+ unless css_content.include?("view-transition")
106
+ css_code = <<~CSS
107
+ .field_with_errors label {
108
+ color: var(--color-destructive);
109
+ }
110
+
111
+ .field_with_errors input {
112
+ border-color: var(--color-destructive);
113
+ }
114
+ CSS
115
+ File.open(css_path, "a") { |f| f.write(css_code) }
116
+ puts " Added: View transition styles to app/assets/stylesheets/application.css"
117
+ end
118
+ end
119
+ end
120
+
121
+ # Copy application layout
122
+ layout_source = File.expand_path("../generators/basecoat/templates/application.html.erb", __dir__)
123
+ layout_destination = Rails.root.join("app/views/layouts/application.html.erb")
124
+
125
+ FileUtils.mkdir_p(File.dirname(layout_destination))
126
+ FileUtils.cp(layout_source, layout_destination)
127
+ puts " Created: app/views/layouts/application.html.erb"
128
+
129
+ # Copy layout partials
130
+ partials_source = File.expand_path("../generators/basecoat/templates/layouts", __dir__)
131
+ partials_destination = Rails.root.join("app/views/layouts")
132
+
133
+ Dir.glob("#{partials_source}/*").each do |file|
134
+ filename = File.basename(file)
135
+ FileUtils.cp(file, partials_destination.join(filename))
136
+ puts " Created: app/views/layouts/#{filename}"
137
+ end
138
+
139
+ # Copy scaffold hook initializer
140
+ initializer_source = File.expand_path("../generators/basecoat/templates/scaffold_hook.rb", __dir__)
141
+ initializer_destination = Rails.root.join("config/initializers/scaffold_hook.rb")
142
+
143
+ FileUtils.mkdir_p(File.dirname(initializer_destination))
144
+ FileUtils.cp(initializer_source, initializer_destination)
145
+ puts " Created: config/initializers/scaffold_hook.rb"
146
+
147
+ puts "\n✓ Basecoat installed successfully!"
148
+ puts " Scaffold templates are automatically available from the gem."
149
+ puts " You can now run: rails generate scaffold YourModel"
150
+ end
151
+
152
+ namespace :install do
153
+ desc "Install Basecoat Devise views and layout"
154
+ task :devise do
155
+ # Copy devise views
156
+ devise_source = File.expand_path("../generators/basecoat/templates/devise", __dir__)
157
+ devise_destination = Rails.root.join("app/views/devise")
158
+
159
+ FileUtils.mkdir_p(devise_destination)
160
+ FileUtils.cp_r("#{devise_source}/.", devise_destination)
161
+ puts " Created: app/views/devise/"
162
+
163
+ # Copy devise layout
164
+ layout_source = File.expand_path("../generators/basecoat/templates/devise.html.erb", __dir__)
165
+ layout_destination = Rails.root.join("app/views/layouts/devise.html.erb")
166
+
167
+ FileUtils.mkdir_p(File.dirname(layout_destination))
168
+ FileUtils.cp(layout_source, layout_destination)
169
+ puts " Created: app/views/layouts/devise.html.erb"
170
+
171
+ # Add user dropdown to header partial
172
+ header_path = Rails.root.join("app/views/layouts/_header.html.erb")
173
+ if File.exist?(header_path)
174
+ header_content = File.read(header_path)
175
+ unless header_content.include?("dropdown-user")
176
+ user_dropdown = <<~HTML
177
+
178
+ <% if defined?(user_signed_in?) && user_signed_in? %>
179
+ <div id="dropdown-user" class="dropdown-menu">
180
+ <button type="button" id="dropdown-user-trigger" aria-haspopup="menu" aria-controls="dropdown-user-menu" aria-expanded="false" class="btn-icon-ghost rounded-full size-8">
181
+ <img alt="<%= current_user.email %>" src="https://github.com/lafeber.png" class="size-8 shrink-0 rounded-full">
182
+ </button>
183
+ <div id="dropdown-user-popover" data-popover="" aria-hidden="true" data-align="end">
184
+ <div role="menu" id="dropdown-user-menu" aria-labelledby="dropdown-user-trigger">
185
+ <div class="px-1 py-1.5">
186
+ <%= button_to destroy_user_session_path, method: :delete, class: "btn-link" do %>
187
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
188
+ Log out
189
+ <% end %>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ <% end %>
195
+ HTML
196
+ updated_content = header_content.sub("<!-- DEVISE_USER_DROPDOWN -->", user_dropdown)
197
+ File.write(header_path, updated_content)
198
+ puts " Added: User dropdown to app/views/layouts/_header.html.erb"
199
+ end
200
+ end
201
+
202
+ puts "\n✓ Basecoat Devise views installed successfully!"
203
+ puts " Make sure you have Devise configured in your application."
204
+ end
205
+
206
+ desc "Install Basecoat Pagy pagination styles"
207
+ task :pagy do
208
+ pagy_source = File.expand_path("../generators/basecoat/templates/pagy.scss", __dir__)
209
+
210
+ # Check if using Tailwind v4 setup (app/assets/tailwind)
211
+ if File.exist?(Rails.root.join("app/assets/tailwind/application.css"))
212
+ # Copy pagy styles to tailwind directory
213
+ pagy_destination = Rails.root.join("app/assets/tailwind/pagy.scss")
214
+ FileUtils.mkdir_p(File.dirname(pagy_destination))
215
+ FileUtils.cp(pagy_source, pagy_destination)
216
+ puts " Created: app/assets/tailwind/pagy.scss"
217
+
218
+ # Add import to tailwind application.css
219
+ tailwind_css = Rails.root.join("app/assets/tailwind/application.css")
220
+ content = File.read(tailwind_css)
221
+ unless content.include?("pagy")
222
+ File.open(tailwind_css, "a") do |f|
223
+ f.puts '@import "./pagy.scss";'
224
+ end
225
+ puts " Added import to: app/assets/tailwind/application.css"
226
+ end
227
+ else
228
+ # Copy pagy styles to stylesheets directory
229
+ pagy_destination = Rails.root.join("app/assets/stylesheets/pagy.scss")
230
+ FileUtils.mkdir_p(File.dirname(pagy_destination))
231
+ FileUtils.cp(pagy_source, pagy_destination)
232
+ puts " Created: app/assets/stylesheets/pagy.scss"
233
+ end
234
+
235
+ puts "\n✓ Basecoat Pagy styles installed successfully!"
236
+ puts " Make sure you have Pagy configured in your application."
237
+ end
238
+
239
+ desc "Install Basecoat authentication views and layout"
240
+ task :authentication do
241
+ # Copy sessions views
242
+ sessions_source = File.expand_path("../generators/basecoat/templates/sessions", __dir__)
243
+ sessions_destination = Rails.root.join("app/views/sessions")
244
+
245
+ FileUtils.mkdir_p(sessions_destination)
246
+ FileUtils.cp_r("#{sessions_source}/.", sessions_destination)
247
+ puts " Created: app/views/sessions/"
248
+
249
+ # Copy passwords views
250
+ passwords_source = File.expand_path("../generators/basecoat/templates/passwords", __dir__)
251
+ passwords_destination = Rails.root.join("app/views/passwords")
252
+
253
+ FileUtils.mkdir_p(passwords_destination)
254
+ FileUtils.cp_r("#{passwords_source}/.", passwords_destination)
255
+ puts " Created: app/views/passwords/"
256
+
257
+ # Copy sessions layout
258
+ layout_source = File.expand_path("../generators/basecoat/templates/sessions.html.erb", __dir__)
259
+ layout_destination = Rails.root.join("app/views/layouts/sessions.html.erb")
260
+
261
+ FileUtils.mkdir_p(File.dirname(layout_destination))
262
+ FileUtils.cp(layout_source, layout_destination)
263
+ puts " Created: app/views/layouts/sessions.html.erb"
264
+
265
+ # Add layout to passwords_controller
266
+ passwords_controller = Rails.root.join("app/controllers/passwords_controller.rb")
267
+ if File.exist?(passwords_controller)
268
+ content = File.read(passwords_controller)
269
+ unless content.include?('layout "sessions"')
270
+ # Add after the class declaration
271
+ updated_content = content.sub(/(class PasswordsController < ApplicationController\n)/, "\\1 layout \"sessions\"\n\n")
272
+ File.write(passwords_controller, updated_content)
273
+ puts " Added layout to: app/controllers/passwords_controller.rb"
274
+ end
275
+ end
276
+
277
+ puts "\n✓ Basecoat authentication views installed successfully!"
278
+ puts " Make sure you have Rails authentication configured in your application."
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,43 @@
1
+ <%%= form_with(model: <%= model_resource_name %>, class: "space-y-6") do |form| %>
2
+ <%%= render "/layouts/form_errors", object: <%= singular_table_name %> if <%= singular_table_name %>.errors.any? %>
3
+
4
+ <% attributes.each do |attribute| -%>
5
+ <% required = attribute.to_s.include?('{null}') -%>
6
+ <div class="grid gap-3">
7
+ <% if attribute.password_digest? -%>
8
+ <%%= form.label :password, class: "label" %>
9
+ <%%= form.password_field :password, class: "input", required: true %>
10
+ </div>
11
+
12
+ <div class="grid gap-3">
13
+ <%%= form.label :password_confirmation, class: "label" %>
14
+ <%%= form.password_field :password_confirmation, class: "input", required: true %>
15
+ <% elsif attribute.attachments? -%>
16
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
17
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: "input"<%= ", required: true" if required %> %>
18
+ <% elsif attribute.field_type == :textarea -%>
19
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
20
+ <%%= form.text_area :<%= attribute.column_name %>, class: "textarea", rows: 4<%= ", required: true" if required %> %>
21
+ <% elsif attribute.field_type == :checkbox -%>
22
+ <%%= form.label :<%= attribute.column_name %>, class: "label" do %>
23
+ <%%= form.check_box :<%= attribute.column_name %>, class: "input", role: "switch" %>
24
+ <%= attribute.human_name %>
25
+ <%% end %>
26
+ <% elsif attribute.field_type == :datetime_local_field || attribute.field_type == :date_field || attribute.field_type == :time_field -%>
27
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
28
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
29
+ <% elsif attribute.field_type == :number_field -%>
30
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
31
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
32
+ <% else -%>
33
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
34
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
35
+ <% end -%>
36
+ </div>
37
+
38
+ <% end -%>
39
+ <div class="flex justify-end space-x-3 pt-6">
40
+ <%%= link_to "Cancel", <%= index_helper(type: :path) %>, class: "btn-outline" %>
41
+ <%%= form.submit class: "btn" %>
42
+ </div>
43
+ <%% end %>
@@ -0,0 +1,21 @@
1
+ <%%= turbo_frame_tag "main_content" do %>
2
+ <%%= render 'layouts/notice', notice: notice if notice %>
3
+ <div class="container mx-auto px-4 py-8">
4
+ <div class="max-w-2xl mx-auto">
5
+ <div class="card">
6
+ <header>
7
+ <h2>Editing <%= human_name.downcase %></h2>
8
+ <p>Update the form below to modify this <%= human_name.downcase %>.</p>
9
+ </header>
10
+ <section>
11
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
12
+ </section>
13
+ </div>
14
+
15
+ <div class="flex flex-wrap gap-3 mt-6">
16
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "btn-outline", data: { turbo_action: "advance" } %>
17
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <%% end %>
@@ -0,0 +1,35 @@
1
+ <%%= turbo_frame_tag "main_content" do %>
2
+ <%%= render 'layouts/notice', notice: notice if notice %>
3
+ <div class="container mx-auto px-4 py-8">
4
+ <div class="flex justify-between items-center mb-8">
5
+ <h1 class="text-3xl"><%= human_name.pluralize %></h1>
6
+ <%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
7
+ </div>
8
+
9
+ <div class="grid gap-4" id="<%= plural_table_name %>">
10
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
11
+ <div class="card">
12
+ <section>
13
+ <%%= render <%= singular_table_name %> %>
14
+ </section>
15
+ <footer class="flex items-center">
16
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
17
+ </footer>
18
+ </div>
19
+ <%% end %>
20
+ </div>
21
+
22
+ <%% if @<%= plural_table_name %>.empty? %>
23
+ <div class="text-center py-12">
24
+ <div class="mb-4">
25
+ <svg class="mx-auto h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
26
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2M4 13h2m13-8V4a1 1 0 00-1-1H7a1 1 0 00-1 1v1h10z" />
27
+ </svg>
28
+ </div>
29
+ <h3 class="text-lg font-medium mb-2">No <%= human_name.pluralize.downcase %> yet</h3>
30
+ <p class="mb-6">Get started by creating your first <%= human_name.downcase %>.</p>
31
+ <%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
32
+ </div>
33
+ <%% end %>
34
+ </div>
35
+ <%% end %>
@@ -0,0 +1,20 @@
1
+ <%%= turbo_frame_tag "main_content" do %>
2
+ <%%= render 'layouts/notice', notice: notice if notice %>
3
+ <div class="container mx-auto px-4 py-8">
4
+ <div class="max-w-2xl mx-auto">
5
+ <div class="card">
6
+ <header>
7
+ <h2>New <%= human_name.downcase %></h2>
8
+ <p>Fill in the form below to create a new <%= human_name.downcase %>.</p>
9
+ </header>
10
+ <section>
11
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
12
+ </section>
13
+ </div>
14
+
15
+ <div class="mt-6">
16
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <%% end %>
@@ -0,0 +1,20 @@
1
+ <div id="<%%= dom_id <%= singular_table_name %> %>" class="space-y-4">
2
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
3
+ <div class="flex flex-col sm:flex-row sm:items-center py-2">
4
+ <dt class="text-sm font-medium sm:w-1/3 mb-1 sm:mb-0">
5
+ <%= attribute.human_name %>:
6
+ </dt>
7
+ <dd class="text-sm sm:w-2/3">
8
+ <% if attribute.attachment? -%>
9
+ <%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %>, target: :_blank, class: "text-blue-600 hover:text-blue-800 underline" if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
10
+ <% elsif attribute.attachments? -%>
11
+ <%% <%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
12
+ <div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %>, target: :_blank, class: "text-blue-600 hover:text-blue-800 underline" %></div>
13
+ <%% end %>
14
+ <% else -%>
15
+ <%%= <%= singular_table_name %>.<%= attribute.column_name %> %>
16
+ <% end -%>
17
+ </dd>
18
+ </div>
19
+ <% end -%>
20
+ </div>
@@ -0,0 +1,23 @@
1
+ <%%= turbo_frame_tag "main_content" do %>
2
+ <%%= render 'layouts/notice', notice: notice if notice %>
3
+ <div class="container mx-auto px-4 py-8">
4
+ <div class="max-w-2xl mx-auto">
5
+ <div class="card">
6
+ <section>
7
+ <%%= render @<%= singular_table_name %> %>
8
+ </section>
9
+ </div>
10
+
11
+ <div class="flex flex-wrap gap-3 mt-6">
12
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "btn", data: { turbo_action: "advance" } %>
13
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "btn-outline", data: { turbo_action: "advance" } %>
14
+ <%%= button_to "Delete this <%= human_name.downcase %>",
15
+ <%= model_resource_name(prefix: "@") %>,
16
+ method: :delete,
17
+ class: "btn-destructive",
18
+ data: { turbo_confirm: "Are you sure you want to delete this <%= human_name.downcase %>?", turbo_action: "advance" },
19
+ form_class: "inline-block" %>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ <%% end %>
data/sig/basecoat.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Basecoat
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: basecoat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Martijn Lafeber
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: tailwindcss-rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '4.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '4.0'
26
+ description: Provides beautiful, production-ready scaffold templates and Devise views
27
+ styled with Basecoat CSS framework
28
+ email:
29
+ - lafeber@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".idea/.gitignore"
35
+ - ".idea/basecoat.iml"
36
+ - ".idea/misc.xml"
37
+ - ".idea/modules.xml"
38
+ - ".idea/vcs.xml"
39
+ - LICENSE.txt
40
+ - README.md
41
+ - Rakefile
42
+ - lib/basecoat.rb
43
+ - lib/basecoat/railtie.rb
44
+ - lib/basecoat/version.rb
45
+ - lib/generators/basecoat/templates/application.html.erb
46
+ - lib/generators/basecoat/templates/devise.html.erb
47
+ - lib/generators/basecoat/templates/devise/confirmations/new.html.erb
48
+ - lib/generators/basecoat/templates/devise/mailer/confirmation_instructions.html.erb
49
+ - lib/generators/basecoat/templates/devise/mailer/email_changed.html.erb
50
+ - lib/generators/basecoat/templates/devise/mailer/password_change.html.erb
51
+ - lib/generators/basecoat/templates/devise/mailer/reset_password_instructions.html.erb
52
+ - lib/generators/basecoat/templates/devise/mailer/unlock_instructions.html.erb
53
+ - lib/generators/basecoat/templates/devise/passwords/edit.html.erb
54
+ - lib/generators/basecoat/templates/devise/passwords/new.html.erb
55
+ - lib/generators/basecoat/templates/devise/registrations/edit.html.erb
56
+ - lib/generators/basecoat/templates/devise/registrations/new.html.erb
57
+ - lib/generators/basecoat/templates/devise/sessions/new.html.erb
58
+ - lib/generators/basecoat/templates/devise/shared/_error_messages.html.erb
59
+ - lib/generators/basecoat/templates/devise/shared/_links.html.erb
60
+ - lib/generators/basecoat/templates/devise/unlocks/new.html.erb
61
+ - lib/generators/basecoat/templates/layouts/_alert.html.erb
62
+ - lib/generators/basecoat/templates/layouts/_aside.html.erb
63
+ - lib/generators/basecoat/templates/layouts/_form_errors.html.erb
64
+ - lib/generators/basecoat/templates/layouts/_head.html.erb
65
+ - lib/generators/basecoat/templates/layouts/_header.html.erb
66
+ - lib/generators/basecoat/templates/layouts/_notice.html.erb
67
+ - lib/generators/basecoat/templates/pagy.scss
68
+ - lib/generators/basecoat/templates/passwords/edit.html.erb
69
+ - lib/generators/basecoat/templates/passwords/new.html.erb
70
+ - lib/generators/basecoat/templates/scaffold_hook.rb
71
+ - lib/generators/basecoat/templates/sessions.html.erb
72
+ - lib/generators/basecoat/templates/sessions/new.html.erb
73
+ - lib/tasks/basecoat.rake
74
+ - lib/templates/erb/scaffold/_form.html.erb.tt
75
+ - lib/templates/erb/scaffold/edit.html.erb.tt
76
+ - lib/templates/erb/scaffold/index.html.erb.tt
77
+ - lib/templates/erb/scaffold/new.html.erb.tt
78
+ - lib/templates/erb/scaffold/partial.html.erb.tt
79
+ - lib/templates/erb/scaffold/show.html.erb.tt
80
+ - sig/basecoat.rbs
81
+ homepage: https://github.com/lafeber/basecoat-rb
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ homepage_uri: https://github.com/lafeber/basecoat-rb
86
+ source_code_uri: https://github.com/lafeber/basecoat-rb
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 3.2.0
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.6.7
102
+ specification_version: 4
103
+ summary: Rails scaffold templates and Devise views styled with Basecoat CSS
104
+ test_files: []