lifeform 0.3.0 → 0.5
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/CHANGELOG.md +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/lib/lifeform/form.rb +43 -7
- data/lib/lifeform/libraries/default/button.rb +52 -0
- data/lib/lifeform/libraries/default/input.rb +2 -3
- data/lib/lifeform/libraries/default/submit_button.rb +16 -0
- data/lib/lifeform/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b554a393fe6d14365108e97b9da374e73da67f0d6728b8605f6d2ddea2f3e3f5
|
4
|
+
data.tar.gz: 5749f82de0a38dd41d7fd75245ed1cab66b0b2550bdabc722620e70c2345bf37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86f68d5c0673570a0e549c2f68afb731b749ab305fb9a3a2f2013820389985cd3468b56263ec738ee113a90c49889cc755efd93427c985788af84e37b83b2d56
|
7
|
+
data.tar.gz: d6f72691ee444c44f78a8b8c1bfb7f93c10105398d77f4be6c593e96d85bf58ee031c7fe30f572a133ebeffdd3791aaed2b99438848e27e51431e4da048690a5
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [0.5.0] - 2022-06-10
|
6
|
+
|
7
|
+
## [0.4.0] - 2022-06-08
|
8
|
+
|
9
|
+
- Add support for submit buttons
|
10
|
+
|
11
|
+
## [0.3.0] - 2022-06-08
|
12
|
+
|
13
|
+
- Add automatic field rendering
|
14
|
+
|
5
15
|
## [0.2.0] - 2022-05-31
|
6
16
|
|
7
17
|
- Fields now support content blocks, conditional rendering
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -20,6 +20,8 @@ Given a form object of:
|
|
20
20
|
class TestForm < Lifeform::Form
|
21
21
|
field :occupation, label: "Your Job", id: "your-occupation", required: true
|
22
22
|
field :age, library: :shoelace, label: "Your Age"
|
23
|
+
|
24
|
+
field :submit, type: :submit_button, label: "Save", class: "font-bold"
|
23
25
|
end
|
24
26
|
```
|
25
27
|
|
@@ -29,6 +31,7 @@ And a template rendering of:
|
|
29
31
|
<%= render TestForm.new(url: "/path") do %>
|
30
32
|
<%= render f.field(:occupation) %>
|
31
33
|
<%= render f.field(:age, value: 47) %>
|
34
|
+
<%= render f.field(:submit) %>
|
32
35
|
<% end %>
|
33
36
|
```
|
34
37
|
|
@@ -44,6 +47,9 @@ You get the following HTML output:
|
|
44
47
|
<form-field name="age">
|
45
48
|
<sl-input type="text" label="Your Age" name="age" value="47" id="age"></sl-input>
|
46
49
|
</form-field>
|
50
|
+
<form-button name="commit">
|
51
|
+
<button class="font-bold" name="commit" type="submit">Save</button>
|
52
|
+
</form-button>
|
47
53
|
</form>
|
48
54
|
```
|
49
55
|
|
data/lib/lifeform/form.rb
CHANGED
@@ -6,7 +6,7 @@ module Lifeform
|
|
6
6
|
FieldDefinition = Struct.new(:type, :library, :parameters)
|
7
7
|
|
8
8
|
# A form object which stores field definitions and can be rendered as a component
|
9
|
-
class Form
|
9
|
+
class Form # rubocop:todo Metrics/ClassLength
|
10
10
|
MODEL_PATH_HELPER = :polymorphic_path
|
11
11
|
|
12
12
|
class << self
|
@@ -25,13 +25,21 @@ module Lifeform
|
|
25
25
|
@fields ||= {}
|
26
26
|
end
|
27
27
|
|
28
|
+
def subforms
|
29
|
+
@subforms ||= {}
|
30
|
+
end
|
31
|
+
|
28
32
|
def field(name, type: :text, library: self.library, **parameters)
|
29
|
-
parameters[:name] = name
|
33
|
+
parameters[:name] = name.to_sym
|
30
34
|
fields[name] = FieldDefinition.new(type, Libraries.const_get(library.to_s.classify), parameters)
|
31
35
|
end
|
32
36
|
|
37
|
+
def subform(name, klass, parent_name: nil)
|
38
|
+
subforms[name.to_sym] = { class: klass, parent_name: parent_name }
|
39
|
+
end
|
40
|
+
|
33
41
|
def library(library_name = nil)
|
34
|
-
@library = library_name if library_name
|
42
|
+
@library = library_name.to_sym if library_name
|
35
43
|
@library ||= :default
|
36
44
|
end
|
37
45
|
|
@@ -65,6 +73,17 @@ module Lifeform
|
|
65
73
|
|
66
74
|
attributes
|
67
75
|
end
|
76
|
+
|
77
|
+
def name_of_model(model)
|
78
|
+
return "" if model.nil?
|
79
|
+
|
80
|
+
if model.respond_to?(:to_model)
|
81
|
+
model.to_model.model_name.param_key
|
82
|
+
else
|
83
|
+
# Or just use basic underscore
|
84
|
+
model.class.name.underscore.tr("/", "_")
|
85
|
+
end
|
86
|
+
end
|
68
87
|
end
|
69
88
|
|
70
89
|
# @return [Object]
|
@@ -82,9 +101,16 @@ module Lifeform
|
|
82
101
|
# @return [Boolean]
|
83
102
|
attr_reader :emit_form_tag
|
84
103
|
|
85
|
-
|
86
|
-
|
104
|
+
# @return [Boolean]
|
105
|
+
attr_reader :parent_name
|
106
|
+
|
107
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
108
|
+
model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, **parameters
|
109
|
+
)
|
110
|
+
@model, @url, @library_name, @parameters, @emit_form_tag, @parent_name =
|
111
|
+
model, url, library, parameters, emit_form_tag, parent_name
|
87
112
|
@library = Libraries.const_get(@library_name.to_s.classify)
|
113
|
+
@subform_instances = {}
|
88
114
|
|
89
115
|
parameters[:method] ||= model.respond_to?(:persisted?) && model.persisted? ? :patch : :post
|
90
116
|
parameters[:accept_charset] ||= "UTF-8"
|
@@ -119,7 +145,7 @@ module Lifeform
|
|
119
145
|
|
120
146
|
def field(name, **field_parameters)
|
121
147
|
# @type [FieldDefinition]
|
122
|
-
field_definition = self.class.fields[name]
|
148
|
+
field_definition = self.class.fields[name.to_sym]
|
123
149
|
# @type [Class<Libraries::Default>]
|
124
150
|
field_library = field_definition.library
|
125
151
|
field_library.object_for_field_definition(
|
@@ -127,6 +153,14 @@ module Lifeform
|
|
127
153
|
)
|
128
154
|
end
|
129
155
|
|
156
|
+
def subform(name, model = nil)
|
157
|
+
@subform_instances[name.to_sym] ||= self.class.subforms[name.to_sym][:class].new(
|
158
|
+
model,
|
159
|
+
emit_form_tag: false,
|
160
|
+
parent_name: self.class.subforms[name.to_sym][:parent_name] || self.class.name_of_model(self.model)
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
130
164
|
def render_in(view_context, &block) # rubocop:disable Metrics
|
131
165
|
form_tag = library::FORM_TAG
|
132
166
|
parameters[:action] ||= url || (model ? view_context.send(self.class.const_get(:MODEL_PATH_HELPER), model) : nil)
|
@@ -134,7 +168,9 @@ module Lifeform
|
|
134
168
|
content = if block
|
135
169
|
view_context.capture(self, &block)
|
136
170
|
else
|
137
|
-
self.class.fields.map { |k, _v| field(k).render_in(self) }.join
|
171
|
+
self.class.fields.map { |k, _v| field(k).render_in(self) }.join.then do |renderings|
|
172
|
+
renderings.respond_to?(:html_safe) ? renderings.html_safe : renderings
|
173
|
+
end
|
138
174
|
end
|
139
175
|
|
140
176
|
return content unless emit_form_tag
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lifeform
|
4
|
+
module Libraries
|
5
|
+
class Default
|
6
|
+
class Button
|
7
|
+
attr_reader :form, :field_definition, :attributes
|
8
|
+
|
9
|
+
WRAPPER_TAG = :form_button
|
10
|
+
BUTTON_TAG = :button
|
11
|
+
|
12
|
+
def initialize(form, field_definition, **attributes)
|
13
|
+
@form = form
|
14
|
+
@field_definition = field_definition
|
15
|
+
@attributes = Lifeform::Form.parameters_to_attributes(field_definition.parameters).merge(attributes)
|
16
|
+
@if = @attributes.delete(:if)
|
17
|
+
@label = @attributes.delete(:label) || "Unlabeled Button"
|
18
|
+
@attributes[:type] ||= :button
|
19
|
+
end
|
20
|
+
|
21
|
+
def render_in(view_context, &block)
|
22
|
+
@view_context = view_context
|
23
|
+
@content = block
|
24
|
+
return "" if !@if.nil? && !@if
|
25
|
+
|
26
|
+
template
|
27
|
+
end
|
28
|
+
|
29
|
+
def template # rubocop:disable Metrics/AbcSize
|
30
|
+
Papercraft.html do |wrapper_tag:, button_tag:, attributes:, field_data:|
|
31
|
+
field_body = proc {
|
32
|
+
send(button_tag, **attributes) do
|
33
|
+
emit field_data[:content] || field_data[:label]
|
34
|
+
end
|
35
|
+
}
|
36
|
+
next field_body.call unless wrapper_tag
|
37
|
+
|
38
|
+
send wrapper_tag, name: attributes[:name], &field_body
|
39
|
+
end.render(
|
40
|
+
wrapper_tag: self.class.const_get(:WRAPPER_TAG),
|
41
|
+
button_tag: self.class.const_get(:BUTTON_TAG),
|
42
|
+
attributes: attributes,
|
43
|
+
field_data: {
|
44
|
+
label: @label,
|
45
|
+
content: @content && @view_context.capture(&@content)
|
46
|
+
}
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -30,10 +30,9 @@ module Lifeform
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def model_name
|
33
|
-
|
33
|
+
name_of_model = @form.class.name_of_model(@model)
|
34
34
|
|
35
|
-
|
36
|
-
@model.class.name.underscore.tr("/", "_")
|
35
|
+
form.parent_name ? "#{form.parent_name}[#{name_of_model}]" : name_of_model
|
37
36
|
end
|
38
37
|
|
39
38
|
def value_for_model
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lifeform
|
4
|
+
module Libraries
|
5
|
+
class Default
|
6
|
+
class SubmitButton < Button
|
7
|
+
def initialize(form, field_definition, **attributes)
|
8
|
+
attributes[:name] ||= "commit"
|
9
|
+
attributes[:type] = :submit
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/lifeform/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lifeform
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bridgetown Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -74,7 +74,9 @@ files:
|
|
74
74
|
- lib/lifeform.rb
|
75
75
|
- lib/lifeform/form.rb
|
76
76
|
- lib/lifeform/libraries/default.rb
|
77
|
+
- lib/lifeform/libraries/default/button.rb
|
77
78
|
- lib/lifeform/libraries/default/input.rb
|
79
|
+
- lib/lifeform/libraries/default/submit_button.rb
|
78
80
|
- lib/lifeform/libraries/shoelace.rb
|
79
81
|
- lib/lifeform/libraries/shoelace/input.rb
|
80
82
|
- lib/lifeform/version.rb
|