basecoat 2.0.1 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1211adbec8da355fa5ec5c1794561f8637b1a0cc08441ad67c560fe550f12b1e
4
- data.tar.gz: 9e7569725fcfd26c137868fa764d6302b29c1011bda90d00a39e253f857a2474
3
+ metadata.gz: 6fa9470ef968e4c5dff1e61b2c016056700d4bac56cb48601d86c7cd6eb0a0e1
4
+ data.tar.gz: 1116eb1741c23532506854d7243c8785431a7ea9957a6ab097ec952ead59d345
5
5
  SHA512:
6
- metadata.gz: 0037adf9df5619c1402db0216bb281f340b5008b954a2cb0c1f278165909d5306037183dd93f839a18b09126a5edec914efab7380c339e928ff0144e3d5145d7
7
- data.tar.gz: b0ebf8d1841064e080c81a4a3ad57cacff757fa78b6e3f1d9534f200e68702d5f4376645ba12aad92509acfea0a0aa28514e54f71370b432a0405209bf924873
6
+ metadata.gz: 9ee345ffafaa76be5521b2fb9c9fade4f527517963acdb1f5cd50d283ff469e8704bde799d0b9c6070ffaa200f916e8d5ebb160416ef2466efabf653ef1c5f7d
7
+ data.tar.gz: e50d6e88672d5f555466e4d12abe0f5dc712b6bb29054403a306964d8fa8ca0d99391a602ae39c3ae588dddb89f00cc96cf5b797de8deed1176178357035b500
data/README.md CHANGED
@@ -3,84 +3,75 @@
3
3
  This gem provides you with amazing layouts, scaffolds, views and partials based on [Basecoat UI](https://basecoatui.com).
4
4
  It is especially powerful for admin applications with a lot of CRUD actions.
5
5
 
6
- Beautiful responsive, dark & light mode Rails scaffolds, pages for authentication and Devise, and pagy styling.
7
-
8
-
9
6
  ![Basecoat Login](basecoat-login.png)
10
7
 
11
- ![Basecoat Index](basecoat-new.png)
12
-
13
- ## Why?
14
-
15
- Shadcn has quickly become the default ui for the web. However, sometimes we don't _really_ need all the React components.
16
- Especially with backend applications - where Rails shines as full stack solution.
17
-
18
- This is where basecoat-ui comes in. The reason why I love basecoat is because it combines tailwind with clean css classes (like daisy-ui).
8
+ ![Basecoat Form](basecoat-new.png)
19
9
 
20
- If you need more complex components; enrich the views with https://railsblocks.com/ or https://shadcn.rails-components.com/ or just the shadcn React components themselves.
10
+ ## Usage
21
11
 
22
- ## Installation
12
+ Try it from scratch:
23
13
 
24
- Add this line to your application's Gemfile in the development group:
14
+ rails new myproject -c tailwind
15
+ cd myproject
16
+ bundle add basecoat
17
+ rails basecoat:install
18
+ rails g scaffold Post title:string! description:text posted_at:datetime active:boolean rating:integer
19
+ rails db:migrate
20
+ ./bin/dev
21
+ # open http://localhost:3000/posts
25
22
 
26
- ```ruby
27
- gem 'basecoat'
28
- ```
23
+ **Note:** Basecoat requires Tailwind CSS. If you haven't installed it yet, follow the instructions at [https://github.com/rails/tailwindcss-rails](https://github.com/rails/tailwindcss-rails) to set up Tailwind CSS in your Rails application.
29
24
 
30
- And then execute:
25
+ ## Why?
31
26
 
32
- ```bash
33
- bundle install
34
- ```
27
+ The default scaffolds are ugly. There's no styling, no turbo frames - it's missing the WOW factor.
35
28
 
36
- **Note:** Basecoat requires Tailwind CSS. If you haven't installed it yet, follow the instructions at [https://github.com/rails/tailwindcss-rails](https://github.com/rails/tailwindcss-rails) to set up Tailwind CSS in your Rails application.
29
+ Basecoat CSS combines tailwind with clean css classes. It creates the looks of shadcn, which has a massive community.
37
30
 
38
- ## Usage
39
-
40
- Run the rake tasks, run a scaffold and observe beauty.
31
+ If you need more complex components; enrich the views with https://railsblocks.com/ or https://shadcn.rails-components.com/ or just the shadcn React components themselves.
41
32
 
42
- ### Install Application Layout
33
+ ## Rake tasks
43
34
 
44
- Install the Basecoat application layout and partials:
35
+ ### Layout (required)
45
36
 
46
37
  ```bash
47
38
  rake basecoat:install
48
39
  ```
49
- NB: This could overwrite exising files!
40
+ NB: Only run this once.
50
41
 
51
42
  The generated views will include:
52
43
  * Basecoat CSS styling
53
44
  * Turbo Frame support for SPA-like navigation
54
- * View transitions
45
+ * A tiny bit of javascript for awesome view transitions
55
46
  * Responsive design
56
47
  * Dark mode support
57
48
  * Form validation with required fields
58
49
  * Boolean fields styled as switches
59
50
  * Automatic sidebar navigation links
60
51
 
61
- The scaffold templates are automatically available from the gem, so you can immediately generate scaffolds:
52
+ The scaffold templates are automatically available from the gem, so you can immediately generate scaffolds.
62
53
 
63
- ```bash
64
- rails generate scaffold Post title:string body:text published:boolean
65
- ```
54
+ ### Default Rails Authentication
66
55
 
67
- ### Install Devise Views
68
-
69
- Install the Basecoat-styled Devise views and layout:
56
+ Install the Basecoat-styled authentication views (for Rails built-in authentication):
57
+
58
+ rails generate:authentication
59
+ rails db:migrate
60
+ rake basecoat:install:authentication
70
61
 
71
- ```bash
72
- rake basecoat:install:devise
73
- ```
74
- NB: This will overwrite exising files!
62
+ NB: To create a user, go to your console:
63
+
64
+ rails console
65
+ User.create(email_address: "email@example.com", password: "basecoat")
66
+ exit
75
67
 
76
- ### Install Authentication Views
68
+ ### Install the Basecoat-styled Devise views and layout:
77
69
 
78
- Install the Basecoat-styled authentication views (for Rails built-in authentication):
70
+ First install devise, follow the instructions at https://github.com/heartcombo/devise. Then:
79
71
 
80
72
  ```bash
81
- rake basecoat:install:authentication
73
+ rake basecoat:install:devise
82
74
  ```
83
- NB: This will overwrite exising files!
84
75
 
85
76
  ### Install Pagy Pagination Styles
86
77
 
@@ -97,19 +88,9 @@ rake basecoat:install:pagy
97
88
  - Basecoat CSS
98
89
  - Stimulus (for the theme toggle, can be moved to something else if you desire...)
99
90
 
100
- ## Discussion
101
-
102
- The scaffolds are more opinionated than the default - it includes a main turbo frame.
103
- I also strongly feel that the index should not reuse the partial used in show - it defeats the purpose of the show page.
104
- A responsive table was the best I could come up with - closer to the OG scaffolds before Hotwire.
105
-
106
- Also, the (arguably) most messy part of the views are the svg tags which contain the lovely lucide icons.
107
- Since these icons are the default for shadcn I'm considering including https://github.com/heyvito/lucide-rails to clean up the views.
108
-
109
91
  ## Issues
110
92
 
111
- * The javascript included by basecoat needs some improvement. It's not automatically initialized on turbo:load - included is a hack that I hope is temporary.
112
- * We include extra css for the definition list. Hopefully this will be part of basecoat-css someday.
93
+ * We include extra css for the definition list. Ideally I would pick an existing component.
113
94
  * Rails adds class="field_with_errors", so we need extra css for this. I hope Rails will at some point have aria-invalid="true" on the input, basecoat will apply the correct styling.
114
95
  * Can the views even be prettier? Probably! I'm more than happy to discuss improvements:
115
96
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basecoat
4
- VERSION = "2.0.1"
4
+ VERSION = "2.2.1"
5
5
  end
@@ -1,8 +1,27 @@
1
1
  require 'fileutils'
2
2
 
3
3
  namespace :basecoat do
4
+ # Helper method to prompt for overwrite confirmation
5
+ def prompt_overwrite(file_path, overwrite_all)
6
+ return true if overwrite_all[:value]
7
+ return true unless File.exist?(file_path)
8
+
9
+ print " Overwrite #{file_path.relative_path_from(Rails.root)}? [y/n/a] "
10
+ response = STDIN.gets.chomp.downcase
11
+
12
+ if response == 'a'
13
+ overwrite_all[:value] = true
14
+ true
15
+ elsif response == 'y'
16
+ true
17
+ else
18
+ false
19
+ end
20
+ end
21
+
4
22
  desc "Install Basecoat application layout and partials"
5
23
  task :install do
24
+ overwrite_all = { value: false }
6
25
  # Install basecoat-css (detect package manager)
7
26
  puts "\n📦 Installing basecoat-css..."
8
27
 
@@ -82,8 +101,12 @@ namespace :basecoat do
82
101
  theme_controller_destination = Rails.root.join("app/javascript/controllers/theme_controller.js")
83
102
 
84
103
  FileUtils.mkdir_p(File.dirname(theme_controller_destination))
85
- FileUtils.cp(theme_controller_source, theme_controller_destination)
86
- puts " Created: app/javascript/controllers/theme_controller.js"
104
+ if prompt_overwrite(theme_controller_destination, overwrite_all)
105
+ FileUtils.cp(theme_controller_source, theme_controller_destination)
106
+ puts " Created: app/javascript/controllers/theme_controller.js"
107
+ else
108
+ puts " Skipped: app/javascript/controllers/theme_controller.js"
109
+ end
87
110
  end
88
111
 
89
112
  # Add CSS imports and styles
@@ -112,23 +135,25 @@ namespace :basecoat do
112
135
  css_content = File.read(css_path)
113
136
 
114
137
  css_code = <<~CSS
115
- .field_with_errors {
116
- label {
117
- color: var(--color-destructive);
118
- }
119
-
120
- input {
121
- border-color: var(--color-destructive);
122
- }
123
- }
124
-
125
- dl {
126
- font-size: var(--text-sm);
127
- dt {
128
- font-weight: var(--font-weight-bold);
129
- margin-top: calc(var(--spacing)*4);
130
- }
131
- }
138
+ dl {
139
+ font-size: var(--text-sm);
140
+ dt {
141
+ font-weight: var(--font-weight-bold);
142
+ margin-top: calc(var(--spacing)*4);
143
+ }
144
+ }
145
+
146
+ label:has(+ input:required):after {
147
+ content: " *"
148
+ }
149
+
150
+ input:user-invalid, .field_with_errors input {
151
+ border-color: var(--color-destructive);
152
+ }
153
+
154
+ label:has(+ input:user-invalid), .field_with_errors label {
155
+ color: var(--color-destructive);
156
+ }
132
157
  CSS
133
158
  File.open(css_path, "a") { |f| f.write(css_code) }
134
159
  puts " Added: basic styles to #{css_path.relative_path_from(Rails.root)}"
@@ -147,30 +172,53 @@ namespace :basecoat do
147
172
  if content =~ /(<head>.*?<\/head>)/m
148
173
  head_content = $1
149
174
  head_destination = partials_destination.join("_head.html.erb")
150
- File.write(head_destination, head_content + "\n")
151
- puts " Created: app/views/layouts/_head.html.erb (extracted from existing application.html.erb)"
175
+ if prompt_overwrite(head_destination, overwrite_all)
176
+ File.write(head_destination, head_content + "\n")
177
+ puts " Created: app/views/layouts/_head.html.erb (extracted from existing application.html.erb)"
178
+ else
179
+ puts " Skipped: app/views/layouts/_head.html.erb"
180
+ end
152
181
  else
153
182
  # Fallback: copy the template if no <head> found in existing layout
154
- FileUtils.cp("#{partials_source}/_head.html.erb", partials_destination.join("_head.html.erb"))
155
- puts " Created: app/views/layouts/_head.html.erb (from template)"
183
+ head_destination = partials_destination.join("_head.html.erb")
184
+ if prompt_overwrite(head_destination, overwrite_all)
185
+ FileUtils.cp("#{partials_source}/_head.html.erb", head_destination)
186
+ puts " Created: app/views/layouts/_head.html.erb (from template)"
187
+ else
188
+ puts " Skipped: app/views/layouts/_head.html.erb"
189
+ end
156
190
  end
157
191
  else
158
192
  # No existing layout, use template
159
- FileUtils.cp("#{partials_source}/_head.html.erb", partials_destination.join("_head.html.erb"))
160
- puts " Created: app/views/layouts/_head.html.erb (from template)"
193
+ head_destination = partials_destination.join("_head.html.erb")
194
+ if prompt_overwrite(head_destination, overwrite_all)
195
+ FileUtils.cp("#{partials_source}/_head.html.erb", head_destination)
196
+ puts " Created: app/views/layouts/_head.html.erb (from template)"
197
+ else
198
+ puts " Skipped: app/views/layouts/_head.html.erb"
199
+ end
161
200
  end
162
201
 
163
202
  # Copy application layout
164
203
  layout_source = File.expand_path("../generators/basecoat/templates/application.html.erb", __dir__)
165
- FileUtils.cp(layout_source, layout_destination)
166
- puts " Created: app/views/layouts/application.html.erb"
204
+ if prompt_overwrite(layout_destination, overwrite_all)
205
+ FileUtils.cp(layout_source, layout_destination)
206
+ puts " Created: app/views/layouts/application.html.erb"
207
+ else
208
+ puts " Skipped: app/views/layouts/application.html.erb"
209
+ end
167
210
 
168
211
  # Copy layout partials (except _head.html.erb which we already handled)
169
212
  Dir.glob("#{partials_source}/*").each do |file|
170
213
  filename = File.basename(file)
171
214
  next if filename == "_head.html.erb" # Skip _head.html.erb, we already created it
172
- FileUtils.cp(file, partials_destination.join(filename))
173
- puts " Created: app/views/layouts/#{filename}"
215
+ destination = partials_destination.join(filename)
216
+ if prompt_overwrite(destination, overwrite_all)
217
+ FileUtils.cp(file, destination)
218
+ puts " Created: app/views/layouts/#{filename}"
219
+ else
220
+ puts " Skipped: app/views/layouts/#{filename}"
221
+ end
174
222
  end
175
223
 
176
224
  # Copy shared partials
@@ -180,8 +228,13 @@ namespace :basecoat do
180
228
  FileUtils.mkdir_p(shared_destination)
181
229
  Dir.glob("#{shared_source}/*").each do |file|
182
230
  filename = File.basename(file)
183
- FileUtils.cp(file, shared_destination.join(filename))
184
- puts " Created: app/views/shared/#{filename}"
231
+ destination = shared_destination.join(filename)
232
+ if prompt_overwrite(destination, overwrite_all)
233
+ FileUtils.cp(file, destination)
234
+ puts " Created: app/views/shared/#{filename}"
235
+ else
236
+ puts " Skipped: app/views/shared/#{filename}"
237
+ end
185
238
  end
186
239
 
187
240
  # Copy scaffold hook initializer
@@ -189,8 +242,12 @@ namespace :basecoat do
189
242
  initializer_destination = Rails.root.join("config/initializers/scaffold_hook.rb")
190
243
 
191
244
  FileUtils.mkdir_p(File.dirname(initializer_destination))
192
- FileUtils.cp(initializer_source, initializer_destination)
193
- puts " Created: config/initializers/scaffold_hook.rb"
245
+ if prompt_overwrite(initializer_destination, overwrite_all)
246
+ FileUtils.cp(initializer_source, initializer_destination)
247
+ puts " Created: config/initializers/scaffold_hook.rb"
248
+ else
249
+ puts " Skipped: config/initializers/scaffold_hook.rb"
250
+ end
194
251
 
195
252
  puts "\n✓ Basecoat installed successfully!"
196
253
  puts " Scaffold templates are automatically available from the gem."
@@ -200,21 +257,37 @@ namespace :basecoat do
200
257
  namespace :install do
201
258
  desc "Install Basecoat Devise views and layout"
202
259
  task :devise do
260
+ overwrite_all = { value: false }
261
+
203
262
  # Copy devise views
204
263
  devise_source = File.expand_path("../generators/basecoat/templates/devise", __dir__)
205
264
  devise_destination = Rails.root.join("app/views/devise")
206
265
 
207
266
  FileUtils.mkdir_p(devise_destination)
208
- FileUtils.cp_r("#{devise_source}/.", devise_destination)
209
- puts " Created: app/views/devise/"
267
+ Dir.glob("#{devise_source}/**/*").each do |file|
268
+ next if File.directory?(file)
269
+ relative_path = Pathname.new(file).relative_path_from(Pathname.new(devise_source))
270
+ destination = devise_destination.join(relative_path)
271
+ FileUtils.mkdir_p(File.dirname(destination))
272
+ if prompt_overwrite(destination, overwrite_all)
273
+ FileUtils.cp(file, destination)
274
+ puts " Created: app/views/devise/#{relative_path}"
275
+ else
276
+ puts " Skipped: app/views/devise/#{relative_path}"
277
+ end
278
+ end
210
279
 
211
280
  # Copy devise layout
212
281
  layout_source = File.expand_path("../generators/basecoat/templates/devise.html.erb", __dir__)
213
282
  layout_destination = Rails.root.join("app/views/layouts/devise.html.erb")
214
283
 
215
284
  FileUtils.mkdir_p(File.dirname(layout_destination))
216
- FileUtils.cp(layout_source, layout_destination)
217
- puts " Created: app/views/layouts/devise.html.erb"
285
+ if prompt_overwrite(layout_destination, overwrite_all)
286
+ FileUtils.cp(layout_source, layout_destination)
287
+ puts " Created: app/views/layouts/devise.html.erb"
288
+ else
289
+ puts " Skipped: app/views/layouts/devise.html.erb"
290
+ end
218
291
 
219
292
  # Add user dropdown to header partial
220
293
  header_path = Rails.root.join("app/views/layouts/_header.html.erb")
@@ -253,6 +326,7 @@ namespace :basecoat do
253
326
 
254
327
  desc "Install Basecoat Pagy pagination styles"
255
328
  task :pagy do
329
+ overwrite_all = { value: false }
256
330
  pagy_source = File.expand_path("../generators/basecoat/templates/pagy.scss", __dir__)
257
331
 
258
332
  # Check if using Tailwind v4 setup (app/assets/tailwind)
@@ -260,8 +334,12 @@ namespace :basecoat do
260
334
  # Copy pagy styles to tailwind directory
261
335
  pagy_destination = Rails.root.join("app/assets/tailwind/pagy.scss")
262
336
  FileUtils.mkdir_p(File.dirname(pagy_destination))
263
- FileUtils.cp(pagy_source, pagy_destination)
264
- puts " Created: app/assets/tailwind/pagy.scss"
337
+ if prompt_overwrite(pagy_destination, overwrite_all)
338
+ FileUtils.cp(pagy_source, pagy_destination)
339
+ puts " Created: app/assets/tailwind/pagy.scss"
340
+ else
341
+ puts " Skipped: app/assets/tailwind/pagy.scss"
342
+ end
265
343
 
266
344
  # Add import to tailwind application.css
267
345
  tailwind_css = Rails.root.join("app/assets/tailwind/application.css")
@@ -276,8 +354,12 @@ namespace :basecoat do
276
354
  # Copy pagy styles to stylesheets directory
277
355
  pagy_destination = Rails.root.join("app/assets/stylesheets/pagy.scss")
278
356
  FileUtils.mkdir_p(File.dirname(pagy_destination))
279
- FileUtils.cp(pagy_source, pagy_destination)
280
- puts " Created: app/assets/stylesheets/pagy.scss"
357
+ if prompt_overwrite(pagy_destination, overwrite_all)
358
+ FileUtils.cp(pagy_source, pagy_destination)
359
+ puts " Created: app/assets/stylesheets/pagy.scss"
360
+ else
361
+ puts " Skipped: app/assets/stylesheets/pagy.scss"
362
+ end
281
363
  end
282
364
 
283
365
  puts "\n✓ Basecoat Pagy styles installed successfully!"
@@ -286,29 +368,55 @@ namespace :basecoat do
286
368
 
287
369
  desc "Install Basecoat authentication views and layout"
288
370
  task :authentication do
371
+ overwrite_all = { value: false }
372
+
289
373
  # Copy sessions views
290
374
  sessions_source = File.expand_path("../generators/basecoat/templates/sessions", __dir__)
291
375
  sessions_destination = Rails.root.join("app/views/sessions")
292
376
 
293
377
  FileUtils.mkdir_p(sessions_destination)
294
- FileUtils.cp_r("#{sessions_source}/.", sessions_destination)
295
- puts " Created: app/views/sessions/"
378
+ Dir.glob("#{sessions_source}/**/*").each do |file|
379
+ next if File.directory?(file)
380
+ relative_path = Pathname.new(file).relative_path_from(Pathname.new(sessions_source))
381
+ destination = sessions_destination.join(relative_path)
382
+ FileUtils.mkdir_p(File.dirname(destination))
383
+ if prompt_overwrite(destination, overwrite_all)
384
+ FileUtils.cp(file, destination)
385
+ puts " Created: app/views/sessions/#{relative_path}"
386
+ else
387
+ puts " Skipped: app/views/sessions/#{relative_path}"
388
+ end
389
+ end
296
390
 
297
391
  # Copy passwords views
298
392
  passwords_source = File.expand_path("../generators/basecoat/templates/passwords", __dir__)
299
393
  passwords_destination = Rails.root.join("app/views/passwords")
300
394
 
301
395
  FileUtils.mkdir_p(passwords_destination)
302
- FileUtils.cp_r("#{passwords_source}/.", passwords_destination)
303
- puts " Created: app/views/passwords/"
396
+ Dir.glob("#{passwords_source}/**/*").each do |file|
397
+ next if File.directory?(file)
398
+ relative_path = Pathname.new(file).relative_path_from(Pathname.new(passwords_source))
399
+ destination = passwords_destination.join(relative_path)
400
+ FileUtils.mkdir_p(File.dirname(destination))
401
+ if prompt_overwrite(destination, overwrite_all)
402
+ FileUtils.cp(file, destination)
403
+ puts " Created: app/views/passwords/#{relative_path}"
404
+ else
405
+ puts " Skipped: app/views/passwords/#{relative_path}"
406
+ end
407
+ end
304
408
 
305
409
  # Copy sessions layout
306
410
  layout_source = File.expand_path("../generators/basecoat/templates/sessions.html.erb", __dir__)
307
411
  layout_destination = Rails.root.join("app/views/layouts/sessions.html.erb")
308
412
 
309
413
  FileUtils.mkdir_p(File.dirname(layout_destination))
310
- FileUtils.cp(layout_source, layout_destination)
311
- puts " Created: app/views/layouts/sessions.html.erb"
414
+ if prompt_overwrite(layout_destination, overwrite_all)
415
+ FileUtils.cp(layout_source, layout_destination)
416
+ puts " Created: app/views/layouts/sessions.html.erb"
417
+ else
418
+ puts " Skipped: app/views/layouts/sessions.html.erb"
419
+ end
312
420
 
313
421
  # Add layout to passwords_controller
314
422
  passwords_controller = Rails.root.join("app/controllers/passwords_controller.rb")
@@ -23,12 +23,15 @@
23
23
  <%%= form.check_box :<%= attribute.column_name %>, class: "input", role: "switch" %>
24
24
  <%= attribute.human_name %>
25
25
  <%% end %>
26
- <% elsif attribute.field_type == :datetime_local_field || attribute.field_type == :date_field || attribute.field_type == :time_field -%>
26
+ <% elsif %w[url permalink website].include? attribute.column_name -%>
27
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 -%>
28
+ <%%= form.url_field :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
29
+ <% elsif %w[email email_address].include? attribute.column_name -%>
30
30
  <%%= form.label :<%= attribute.column_name %>, class: "label" %>
31
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
31
+ <%%= form.email_field :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
32
+ <% elsif %w[phone phone_number].include? attribute.column_name -%>
33
+ <%%= form.label :<%= attribute.column_name %>, class: "label" %>
34
+ <%%= form.phone_field :<%= attribute.column_name %>, maxLength: 16, pattern: "[0-9\+\\-\\(\\)\s]*", class: "input"<%= ", required: true" if required %> %>
32
35
  <% else -%>
33
36
  <%%= form.label :<%= attribute.column_name %>, class: "label" %>
34
37
  <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input"<%= ", required: true" if required %> %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basecoat
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martijn Lafeber