swage 0.1.0
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 +7 -0
- data/LICENSE.txt +19 -0
- data/README.md +15 -0
- data/lib/generators/swage/USAGE +5 -0
- data/lib/generators/swage/base_generator.rb +14 -0
- data/lib/generators/swage/generators/generators_generator.rb +42 -0
- data/lib/generators/swage/install/install_generator.rb +170 -0
- data/lib/generators/swage/install/templates/application_controller.rb.tt +14 -0
- data/lib/generators/swage/install/templates/application_view.rb.tt +44 -0
- data/lib/generators/swage/install/templates/base_component.rb.tt +6 -0
- data/lib/generators/swage/install/templates/base_view.rb.tt +17 -0
- data/lib/generators/swage/install/templates/engine.rb.tt +25 -0
- data/lib/generators/swage/install/templates/form.rb.tt +209 -0
- data/lib/generators/swage/install/templates/swage.rb.tt +28 -0
- data/lib/generators/swage/install/templates/tw-animate-css.js.tt +580 -0
- data/lib/generators/swage/scaffold/scaffold_generator.rb +27 -0
- data/lib/generators/swage/scaffold/templates/controller.rb.tt +59 -0
- data/lib/generators/swage/scaffold/templates/edit.rb.tt +27 -0
- data/lib/generators/swage/scaffold/templates/form.rb.tt +41 -0
- data/lib/generators/swage/scaffold/templates/index.rb.tt +39 -0
- data/lib/generators/swage/scaffold/templates/new.rb.tt +23 -0
- data/lib/generators/swage/scaffold/templates/partial.rb.tt +24 -0
- data/lib/generators/swage/scaffold/templates/show.rb.tt +36 -0
- data/lib/swage.rb +3 -0
- metadata +150 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1eb99b2b002dccde7c9d242952b711e4d0fc2432b8c46c792e529b22d83e3486
|
|
4
|
+
data.tar.gz: f4eabce375c4ffe258ee251297915ba55916eeafbac9e120b1929e5c87701ae4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d409d145064d845053c9a91db02fd017877c6d745918f95ce5d59627b4ec588ce6cc6ef6414aa66050169384a10add1f694a9b20c992ac3639e62c6dd44985bf
|
|
7
|
+
data.tar.gz: 7f16fbe0f753870da630dfc455507bac3734204c0da4efc7fd420a170028ea7af8372227adf39962fdc0e2e0da8a0fbd655758c46834a72e14f3f23ced1cc24f
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Swage
|
|
2
|
+
Basically a different implementation of [Superview](https://github.com/rubymonolith/superview), but with a few extra goodies and generators baked in. Use [Phlex](https://github.com/yippee-fun/phlex-rails/) for rendering views and [Superform](https://github.com/rubymonolith/superform/) for the form DSL and strong parameters. Uses [RubyUI](https://github.com/ruby-ui/ruby_ui) for the base UI components and [Phlexible](https://github.com/joelmoss/phlexible) to glue everything together (along with a lot of monkeypatching).
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
Simply run `rails g swage:install`, and all of the necessary components will be generated. Please not this might take a while to run.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
By default Swage will hook into the rails scaffold engine. However, it is a drop-in replacement for the erb scaffold_controller, meaning it can be used in the exact same way.
|
|
9
|
+
|
|
10
|
+
## Modification
|
|
11
|
+
If you wish to modify the generators, use `rails g swage:generators` to generate all of the scaffold and install generators/templates.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## TODO
|
|
15
|
+
* Consolidate the Tailwind classes down for the non-RubyUI components
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Swage::Generators
|
|
4
|
+
class BaseGenerator < ::Rails::Generators::NamedBase
|
|
5
|
+
include Rails::Generators::ResourceHelpers
|
|
6
|
+
def self.set_source_root(file_name, dir)
|
|
7
|
+
if File.exist?(Rails.root.join("lib/generators/swage", file_name))
|
|
8
|
+
source_root Rails.root.join("lib/generators/swage/templates")
|
|
9
|
+
else
|
|
10
|
+
source_root File.expand_path("templates", dir)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Swage::Generators
|
|
4
|
+
class GeneratorsGenerator < ::Rails::Generators::Base
|
|
5
|
+
source_root File.expand_path __dir__
|
|
6
|
+
|
|
7
|
+
# there's probably a better way to do this, but this should probably work well enough?
|
|
8
|
+
def create_scaffold_files
|
|
9
|
+
base = File.join "generators", "swage", "scaffold"
|
|
10
|
+
|
|
11
|
+
Dir.chdir("#{source_paths.first}/../scaffold") do
|
|
12
|
+
lib File.join(base, "scaffold_generator.rb"), File.open("scaffold_generator.rb", "r").read
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Dir.chdir("#{source_paths.first}/../scaffold/templates") do
|
|
16
|
+
Dir.glob("*.rb.tt").each do |template|
|
|
17
|
+
lib File.join(base, "templates", template), File.open(template, "r").read
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_install_files
|
|
23
|
+
base = File.join "generators", "swage", "install"
|
|
24
|
+
Dir.chdir("#{source_paths.first}/../install") do
|
|
25
|
+
lib File.join(base, "install_generator.rb"), File.open("install_generator.rb", "r").read
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Dir.chdir("#{source_paths.first}/../install/templates") do
|
|
29
|
+
Dir.glob("*.rb.tt").each do |template|
|
|
30
|
+
lib File.join(base, "templates", template), File.open(template, "r").read
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create_base_generator
|
|
36
|
+
base = File.join "generators", "swage"
|
|
37
|
+
Dir.chdir("#{source_paths.first}/..") do
|
|
38
|
+
lib File.join(base, "base_generator.rb"), File.open("base_generator.rb", "r").read
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Swage::Generators
|
|
4
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
|
6
|
+
|
|
7
|
+
class_option :engine, type: :boolean, default: false
|
|
8
|
+
class_option :override, type: :boolean, default: false
|
|
9
|
+
|
|
10
|
+
@name = nil
|
|
11
|
+
|
|
12
|
+
def check_for_engine
|
|
13
|
+
@engine = options["engine"] # set use instance variables because they look nicer
|
|
14
|
+
|
|
15
|
+
if probably_engine? && !@engine
|
|
16
|
+
if yes?("This appears to be an engine. do you wish to insatll swage as such?")
|
|
17
|
+
say "Installing in engine mode. Hint: use `rails g swage:install --engine`"
|
|
18
|
+
@engine = true
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def check_for_override
|
|
24
|
+
if @engine
|
|
25
|
+
@override = options["override"]
|
|
26
|
+
else
|
|
27
|
+
@override = true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def check_for_js
|
|
32
|
+
return if @engine # engines don't have their own js ecosystem
|
|
33
|
+
unless using_importmap? || using_bun? || using_yarn? || using_npm? || using_pnpm?
|
|
34
|
+
if yes?("No javascript package manager was detected. Do you wish to exit now, or continue and install missing requirements manually?")
|
|
35
|
+
exit 0
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_dependencies
|
|
41
|
+
deps = %W[ tailwindcss-rails phlex-rails phlexible superform ruby_ui ]
|
|
42
|
+
missing = []
|
|
43
|
+
deps.each do |d|
|
|
44
|
+
unless Gem.loaded_specs.has_key?(d)
|
|
45
|
+
say "missing #{d} in gemfile"
|
|
46
|
+
missing << d
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if missing.any?
|
|
51
|
+
return if @engine && missing.length == 1 && missing[0] == "ruby_ui"
|
|
52
|
+
if yes?("would you like to automatically install the missing dependencies?")
|
|
53
|
+
add_source "https://rubygems.org" do
|
|
54
|
+
deps.each do |d|
|
|
55
|
+
gem d
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
exit 1
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# because rails is silly and won't let you do stuff unless you have everything as a gem already
|
|
64
|
+
return if @engine && !@override
|
|
65
|
+
add_source "https://rubygems.org" do
|
|
66
|
+
gem "tailwindcss-rails"
|
|
67
|
+
gem "phlex"
|
|
68
|
+
gem "superform"
|
|
69
|
+
# gem "rogue"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def install_tailwind
|
|
74
|
+
if !@engine || (@engine && @override)
|
|
75
|
+
say "install tailwind"
|
|
76
|
+
execute_command "rake", "tailwindcss:install"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def install_phlex
|
|
81
|
+
return if @engine
|
|
82
|
+
say "install phlex"
|
|
83
|
+
generate "phlex:install"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def install_superform
|
|
87
|
+
return if @engine
|
|
88
|
+
say "install superform"
|
|
89
|
+
generate "superform:install"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def insatll_ruby_ui
|
|
93
|
+
if !@engine || (@engine && @override)
|
|
94
|
+
say "install rubyui"
|
|
95
|
+
generate "ruby_ui:install"
|
|
96
|
+
generate "ruby_ui:component:all"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def install_tw_animate_css # because this file is usually missing while installing ruby_ui
|
|
101
|
+
template "tw-animate-css.js.tt", File.join(destination_root, "vendor/javascript/tw-animate-css.js") unless @engine
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def create_initializer
|
|
105
|
+
say "install swage"
|
|
106
|
+
template "swage.rb.tt", File.join(destination_root, "config/initializers/swage.rb"), force: true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def create_base_component
|
|
110
|
+
template "base_component.rb.tt", File.join(destination_root, "app/components/base.rb"), force: true if @override
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def create_base_view
|
|
114
|
+
template "base_view.rb.tt", File.join(destination_root, "app/views/base.rb"), force: true if @override
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def create_base_form
|
|
118
|
+
template "form.rb.tt", File.join(destination_root, "app/components/form.rb"), force: true if @override
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def modify_application_controller
|
|
122
|
+
template "application_controller.rb.tt", File.join(destination_root, "app/controllers/application_controller.rb") if @override
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def create_application_view
|
|
126
|
+
remove_file File.join(destination_root, "app/views/layouts/application.html.erb")
|
|
127
|
+
template "application_view.rb.tt", File.join(destination_root, "app/views/layouts/application.rb") if @override
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def modify_engine
|
|
131
|
+
return unless @engine
|
|
132
|
+
@name ||= get_name
|
|
133
|
+
template "engine.rb.tt", File.join(destination_root, "lib", get_name, "engine.rb")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private # copied from ruby_ui installer since that's what it uses
|
|
137
|
+
def using_importmap?
|
|
138
|
+
File.exist?(Rails.root.join("config/importmap.rb")) && File.exist?(Rails.root.join("bin/importmap"))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def using_bun?
|
|
142
|
+
File.exist?(Rails.root.join("bun.lock"))
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def using_npm?
|
|
146
|
+
File.exist?(Rails.root.join("package-lock.json"))
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def using_pnpm?
|
|
150
|
+
File.exist?(Rails.root.join("pnpm-lock.yaml"))
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def using_yarn?
|
|
154
|
+
File.exist?(Rails.root.join("yarn.lock"))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def probably_engine?
|
|
158
|
+
@name = get_name
|
|
159
|
+
|
|
160
|
+
# Dir.glob(File.join(destination_root, "test", "dummy")).empty? ||
|
|
161
|
+
# Dir.glob(File.join(destination_root, "*.gemspec")).empty? ||
|
|
162
|
+
File.exist?(File.join(destination_root, "lib", @name, "engine.rb")) ||
|
|
163
|
+
File.exist?(File.join(destination_root, "lib", @name, "railtie.rb"))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def get_name
|
|
167
|
+
destination_root.match(/\w+$/)[0] # this is gross but there seems to be no better way
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class ApplicationController < ActionController::Base
|
|
2
|
+
include Phlexible::Rails::ActionController::ImplicitRender
|
|
3
|
+
include Superform::Rails::StrongParameters
|
|
4
|
+
|
|
5
|
+
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
|
6
|
+
allow_browser versions: :modern
|
|
7
|
+
|
|
8
|
+
# Changes to the importmap will invalidate the etag for HTML responses
|
|
9
|
+
stale_when_importmap_changes
|
|
10
|
+
|
|
11
|
+
def phlex_view_path(action_name)
|
|
12
|
+
"views/#{controller_path}/#{action_name}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Views
|
|
2
|
+
module Layouts
|
|
3
|
+
class Application < Phlex::HTML
|
|
4
|
+
include Phlex::Rails::Helpers::ContentFor
|
|
5
|
+
include Phlex::Rails::Helpers::CSPMetaTag
|
|
6
|
+
include Phlex::Rails::Helpers::CSRFMetaTags
|
|
7
|
+
include Phlex::Rails::Helpers::StyleSheetLinkTag
|
|
8
|
+
include Phlex::Rails::Helpers::JavaScriptImportmapTags
|
|
9
|
+
|
|
10
|
+
def initialize(view)
|
|
11
|
+
@view = view
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template(&block)
|
|
15
|
+
html do
|
|
16
|
+
head do
|
|
17
|
+
title { content_for(:title) || "Asdf" }
|
|
18
|
+
meta(name: "viewport", content: "width=device-width,initial-scale=1")
|
|
19
|
+
meta(name: "apple-mobile-web-app-capable", content: "yes")
|
|
20
|
+
meta(name: "application-name", content: "Asdf")
|
|
21
|
+
meta(name: "mobile-web-app-capable", content: "yes")
|
|
22
|
+
|
|
23
|
+
csrf_meta_tags
|
|
24
|
+
csp_meta_tag
|
|
25
|
+
|
|
26
|
+
# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!)
|
|
27
|
+
# = tag.link rel: "manifest", href: pwa_manifest_path(format: :json)
|
|
28
|
+
link(rel: "icon", href: "/icon.png", type: "image/png")
|
|
29
|
+
link(rel: "icon", href: "/icon.svg", type: "image/svg+xml")
|
|
30
|
+
link(rel: "apple-touch-icon", href: "/icon.png")
|
|
31
|
+
|
|
32
|
+
# Includes all stylesheet files in app/assets/stylesheets
|
|
33
|
+
stylesheet_link_tag :app, "data-turbo-track": "reload"
|
|
34
|
+
stylesheet_link_tag "tailwind", "data-turbo-track": "reload"
|
|
35
|
+
javascript_importmap_tags
|
|
36
|
+
end
|
|
37
|
+
body do
|
|
38
|
+
div id: "body", &block
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Views::Base < Phlex::HTML
|
|
4
|
+
include Phlexible::Rails::AElement
|
|
5
|
+
include Phlexible::Rails::ControllerVariables
|
|
6
|
+
include Phlexible::Callbacks
|
|
7
|
+
include RubyUI
|
|
8
|
+
include Rails.application.routes.url_helpers
|
|
9
|
+
|
|
10
|
+
# More caching options at https://www.phlex.fun/components/caching
|
|
11
|
+
def cache_store = Rails.cache
|
|
12
|
+
|
|
13
|
+
# set up layout paths
|
|
14
|
+
def self.auto_layout_view_prefix = "Views::"
|
|
15
|
+
def self.auto_layout_namespace = "Views::Layouts::"
|
|
16
|
+
def self.auto_layout_default = "Views::Layouts::Application"
|
|
17
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module <%= @name.capitalize %>
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
initializer "<%= @name %>.set_autoloading" do
|
|
4
|
+
module ::Views; end
|
|
5
|
+
|
|
6
|
+
Rails.autoloaders.main.push_dir root.join("app/views"), namespace: ::Views
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Uncomment to automatically include migrations into the application's migration path
|
|
10
|
+
# This avoids copying migrations to the main application
|
|
11
|
+
# initializer "<%= @name %>.add_migrations" do |app|
|
|
12
|
+
# unless app.root.to_s == root.to_s
|
|
13
|
+
# config.paths["db/migrate"].expanded.each do |expanded_path|
|
|
14
|
+
# app.config.paths["db/migrate"] << expanded_path
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
|
|
19
|
+
config.generators do |g|
|
|
20
|
+
g.scaffold_controller :swage
|
|
21
|
+
|
|
22
|
+
g.fallbacks[:swage] = :scaffold_controller
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
module Components
|
|
2
|
+
class Form < Superform::Rails::Form
|
|
3
|
+
include Phlexible::Callbacks
|
|
4
|
+
include Phlex::Rails::Helpers::FormAuthenticityToken
|
|
5
|
+
include RubyUI
|
|
6
|
+
|
|
7
|
+
# monkeypatch superform here because editing superform itself is gross
|
|
8
|
+
class Field < self::Field
|
|
9
|
+
include RubyUI
|
|
10
|
+
def input(**attributes)
|
|
11
|
+
attributes.merge! dom_hash(field.dom)
|
|
12
|
+
RubyUI::Input.new(**attributes)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def checkbox(index: nil, **attributes)
|
|
16
|
+
attributes.merge! dom_hash(field.dom)
|
|
17
|
+
RubyUI::Checkbox.new(**attributes)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def textarea(**attributes)
|
|
21
|
+
attributes.merge! dom_hash(field.dom)
|
|
22
|
+
RubyUI::Textarea.new(**attributes) { attributes[:value] }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def select(*options, multiple: false, **attributes, &)
|
|
26
|
+
attributes.merge! dom_hash(field.dom)
|
|
27
|
+
if mutliple
|
|
28
|
+
CheckboxGroup do
|
|
29
|
+
options.each do |opt|
|
|
30
|
+
div class: "flex flex-col gap-2" do
|
|
31
|
+
div class: "flex flex-row items-center gap-2" do
|
|
32
|
+
RubyUI::Checkbox(*attributes, id: "select_#{opt}")
|
|
33
|
+
FormFieldLabel(for: "select_#{opt}") { opt.capitalize }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
RubyUI::Select(**attributes) do
|
|
40
|
+
SelectGroup do
|
|
41
|
+
options.each do |opt|
|
|
42
|
+
SelectItem(value: opt) { opt.capitalize }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# not sure if this is actually needed or if we can just use a combobox or something similar
|
|
50
|
+
# def datalist(*options, **attributes, &block)
|
|
51
|
+
# Components::Datalist.new(field, options:, **attributes, &block)
|
|
52
|
+
# end
|
|
53
|
+
|
|
54
|
+
def errors
|
|
55
|
+
object.errors[key]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def invalid?
|
|
59
|
+
errors.any?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def valid?
|
|
63
|
+
not invalid?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def human_attribute_name
|
|
67
|
+
object.class.human_attribute_name key
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def text(**attributes)
|
|
71
|
+
attributes.merge! dom_hash(field.dom).merge(type: :text)
|
|
72
|
+
RubyUI::Input(**attributes)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def hidden(**attributes)
|
|
76
|
+
attributes.merge! dom_hash(field.dom).merge(type: :hidden)
|
|
77
|
+
RubyUI::Input(**attributes)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def password(**attributes)
|
|
81
|
+
attributes.merge! dom_hash(field.dom).merge(type: :password)
|
|
82
|
+
RubyUI::Input(**attributes)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def email(**attributes)
|
|
86
|
+
attributes.merge! dom_hash(field.dom).merge(type: :email)
|
|
87
|
+
RubyUI::Input(**attributes)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def url(**attributes)
|
|
91
|
+
attributes.merge! dom_hash(field.dom).merge(type: :url)
|
|
92
|
+
RubyUI::Input(**attributes)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def tel(**attributes)
|
|
96
|
+
attributes.merge! dom_hash(field.dom).merge(type: :tel)
|
|
97
|
+
RubyUI::Input(**attributes)
|
|
98
|
+
end
|
|
99
|
+
alias_method :phone, :tel
|
|
100
|
+
|
|
101
|
+
def number(**attributes)
|
|
102
|
+
RubyUI::Input(**attributes)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def range(**attributes)
|
|
106
|
+
RubyUI::Input(**attributes)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def date(**attributes)
|
|
110
|
+
attributes.merge! dom_hash(field.dom)
|
|
111
|
+
RubyUI::DatePicker(**attributes)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def time(**attributes)
|
|
115
|
+
attributes.merge! dom_hash(field.dom).merge(type: :time)
|
|
116
|
+
RubyUI::Input(**attributes)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def datetime(**attributes)
|
|
120
|
+
attributes.merge! dom_hash(field.dom).merge(type: :"datetime-local")
|
|
121
|
+
RubyUI::Input(**attributes)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def month(**attributes)
|
|
125
|
+
attributes.merge! dom_hash(field.dom).merge(type: :month)
|
|
126
|
+
RubyUI::Input(**attributes)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def week(**attributes)
|
|
130
|
+
attributes.merge! dom_hash(field.dom).merge(type: :week)
|
|
131
|
+
RubyUI::Input(**attributes)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def color(**attributes)
|
|
135
|
+
attributes.merge! dom_hash(field.dom).merge(type: :color)
|
|
136
|
+
RubyUI::Input(**attributes)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def search(**attributes)
|
|
140
|
+
attributes.merge! dom_hash(field.dom).merge(type: :search)
|
|
141
|
+
RubyUI::Input(**attributes)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def file(**attributes)
|
|
145
|
+
attributes.merge! dom_hash(field.dom).merge(type: :file)
|
|
146
|
+
RubyUI::Input(**attributes)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def radio(value, index: value, **attributes)
|
|
150
|
+
attributes.merge! dom_hash(field.dom)
|
|
151
|
+
div class: "clex items-center space-x-2" do
|
|
152
|
+
RubyUI::RadioButton(id: index)
|
|
153
|
+
FormFieldLabel(for: index) { value }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def radios(*options, **attributes, &block)
|
|
158
|
+
options = enum_options if options.empty?
|
|
159
|
+
Components::Radios.new(field, options:, **attributes, &block)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def checkboxes(*options, **attributes, &block)
|
|
163
|
+
options = enum_options if options.empty?
|
|
164
|
+
attributes.merge! dom_hash(field.dom)
|
|
165
|
+
|
|
166
|
+
CheckboxGroup do
|
|
167
|
+
options.each do |opt|
|
|
168
|
+
div class: "flex flex-col gap-2" do
|
|
169
|
+
div class: "flex flex-row items-center gap-2" do
|
|
170
|
+
RubyUI::Checkbox(*attributes, id: "select_#{opt}")
|
|
171
|
+
FormFieldLabel(for: "select_#{opt}") { opt.capitalize }
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Rails compatibility aliases
|
|
179
|
+
alias_method :check_box, :checkbox
|
|
180
|
+
alias_method :text_area, :textarea
|
|
181
|
+
|
|
182
|
+
def title
|
|
183
|
+
key.to_s.titleize
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
private
|
|
187
|
+
# superform has a field with a dom that stores useful values... must convert it to usable attributes
|
|
188
|
+
def dom_hash(dom)
|
|
189
|
+
{
|
|
190
|
+
id: dom.id,
|
|
191
|
+
name: dom.name,
|
|
192
|
+
value: dom.value
|
|
193
|
+
}
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def around_template(&)
|
|
198
|
+
super do
|
|
199
|
+
yield if block_given?
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def submit(value = submit_value, **attributes)
|
|
204
|
+
div do
|
|
205
|
+
RubyUI::Button(name: "commit", type: "submit", **attributes) { submit_value }
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "phlexible"
|
|
4
|
+
|
|
5
|
+
Rails.application.config.generators do |g|
|
|
6
|
+
g.scaffold_controller :swage
|
|
7
|
+
|
|
8
|
+
g.fallbacks[:swage] = :scaffold_controller
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Phlexible::Rails::ButtonToConcerns
|
|
12
|
+
# use consistent ui components
|
|
13
|
+
def view_template(&block)
|
|
14
|
+
action = url_for(@url)
|
|
15
|
+
@options = DEFAULT_OPTIONS.merge((@options || {}).symbolize_keys)
|
|
16
|
+
|
|
17
|
+
method = (@options.delete(:method).presence || method_for_options(@options)).to_s
|
|
18
|
+
form_method = method == "get" ? "get" : "post"
|
|
19
|
+
|
|
20
|
+
form action: action, method: form_method, **form_attributes do
|
|
21
|
+
method_tag method
|
|
22
|
+
form_method == "post" && token_input(action, method.empty? ? "post" : method)
|
|
23
|
+
param_inputs
|
|
24
|
+
|
|
25
|
+
block_given? ? RubyUI::Button(**button_attrs, &block) : RubyUI::Button(**button_attrs) { @name }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|