phlex-forms 0.2.8 → 0.3.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 +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/forms/field.rb +12 -1
- data/lib/forms/file_input.rb +4 -1
- data/lib/forms/hidden.rb +30 -0
- data/lib/phlex_forms/class_merge.rb +17 -7
- data/lib/phlex_forms/delegated_field.rb +4 -1
- data/lib/phlex_forms/theme.rb +5 -3
- data/lib/phlex_forms/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f09c916a2ff918b4abceddb58267e59d2a7584090aabb8daeacfd2112bf36d9f
|
|
4
|
+
data.tar.gz: b19313a3517a7289a7dc46575e47965ce62849c712cdf27cc6e3fd0cbed13db8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 557674f0906795a1f9a09e9d815c6b398b1cd8e8dfd60481512815c85cf276dc3372543272771a1b5dd5cb1a20f45c475bf2254c89d3ab303b1f997b9a1df067
|
|
7
|
+
data.tar.gz: 3994c3583c2c091b0f035df86f3ad9f0428ad7b955cd03bdb8c649756e0840cb474cbba290c916445919fff6afcb73f84f6dca948294a4b7970d2ba43e8b6b30
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`FileInput` multiple uploads submit an array** (Rails `file_field` parity):
|
|
13
|
+
with `multiple:` set, the input name now gets `[]` appended (unless already
|
|
14
|
+
present), for the standalone component, the `Plain` variant, and the form
|
|
15
|
+
builder path. Without it the browser collapsed a multi-file selection into
|
|
16
|
+
ONE scalar param, which a host app's `params.expect(attr: [])` silently
|
|
17
|
+
discarded — uploads no-opped with a success response.
|
|
18
|
+
|
|
10
19
|
### Added
|
|
11
20
|
|
|
12
21
|
- **`checkbox_group` — batched checkbox group for array-valued fields** (the
|
|
@@ -45,6 +54,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
45
54
|
|
|
46
55
|
### Fixed
|
|
47
56
|
|
|
57
|
+
- **A caller width class stacked with the `w-full` default instead of replacing
|
|
58
|
+
it**: `DelegatedField#width_class` joined `"w-full"` and the caller's
|
|
59
|
+
`class:` verbatim, so `Forms::Select(class: "w-36")` emitted
|
|
60
|
+
`class="... w-full w-36"` and stylesheet source order — not author intent —
|
|
61
|
+
picked the winner (in practice `w-full`, which blew filter selects up to full
|
|
62
|
+
width; zazu#2934). `ClassMerge` gained a width family (anchored `w-*`, so
|
|
63
|
+
`min-w-*`/`max-w-*` still compose) and `width_class` merges through it —
|
|
64
|
+
last width wins, matching the daisyui size/color family semantics.
|
|
65
|
+
|
|
48
66
|
- **`f.Radio` / `Field#radio` rendered the model's current value on every radio
|
|
49
67
|
instead of each radio's own value**: `field_attributes` carried `value:
|
|
50
68
|
field_value` and was splatted after the explicit positional value, clobbering
|
data/lib/forms/field.rb
CHANGED
|
@@ -30,6 +30,12 @@ module Forms
|
|
|
30
30
|
# PhlexForms::Theme), so the same field renders daisy or plain.
|
|
31
31
|
|
|
32
32
|
def input(*modifiers, type: :text, **)
|
|
33
|
+
# type: :hidden reroutes to #hidden so EVERY path to a hidden field lands on
|
|
34
|
+
# the bare leaf — `f.Input(:token, :hidden)` and `f.Input(:token, type:
|
|
35
|
+
# :hidden)` would otherwise still emit the styled `input w-full`. Positional
|
|
36
|
+
# modifiers are dropped with it: a hidden field has no visual variants.
|
|
37
|
+
return hidden(**) if type.to_s == "hidden"
|
|
38
|
+
|
|
33
39
|
theme[:input].new(*modifiers, type:, **field_attributes, **)
|
|
34
40
|
end
|
|
35
41
|
|
|
@@ -43,8 +49,13 @@ module Forms
|
|
|
43
49
|
end
|
|
44
50
|
alias rich_text_area rich_textarea
|
|
45
51
|
|
|
52
|
+
# Bare <input type="hidden">, never the styled :input leaf — daisyui's
|
|
53
|
+
# `.input` beats WebKit's non-!important `input[type=hidden] { display: none }`
|
|
54
|
+
# and turns the field into a focusable phantom tab stop in Safari. Built from
|
|
55
|
+
# the explicit accessors (not field_attributes) so the meaningless
|
|
56
|
+
# `error: invalid?` is never introduced.
|
|
46
57
|
def hidden(**)
|
|
47
|
-
theme[:
|
|
58
|
+
theme[:hidden].new(name: field_name, id: field_id, value: field_value, **)
|
|
48
59
|
end
|
|
49
60
|
|
|
50
61
|
# daisyui v5 "icon/text inside the field" wrapper. The block renders the
|
data/lib/forms/file_input.rb
CHANGED
|
@@ -8,7 +8,10 @@ module Forms
|
|
|
8
8
|
def initialize(*modifiers, name: nil, id: nil, multiple: false, accept: nil,
|
|
9
9
|
error: false, disabled: false, required: false, full_width: true, **attributes)
|
|
10
10
|
@modifiers = normalize_modifiers(modifiers)
|
|
11
|
-
|
|
11
|
+
# Rails file_field parity: a multiple input needs an array param name, or
|
|
12
|
+
# the browser collapses the selection into one scalar file — which a host
|
|
13
|
+
# app's `params.expect(attr: [])` then silently discards.
|
|
14
|
+
@name = multiple && name && !name.to_s.end_with?("[]") ? "#{name}[]" : name
|
|
12
15
|
@id = id
|
|
13
16
|
@multiple = multiple
|
|
14
17
|
@accept = accept
|
data/lib/forms/hidden.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Forms
|
|
4
|
+
# A model-bound hidden field: a bare <input type="hidden"> carrying name/id/
|
|
5
|
+
# value plus whatever the caller passes through. Deliberately NOT a
|
|
6
|
+
# DelegatedField/DaisyUI::Input like Forms::Input — a hidden field must never
|
|
7
|
+
# carry visual styling. daisyui's `.input { display: inline-flex }` overrides
|
|
8
|
+
# WebKit's *non*-!important UA rule `input[type=hidden] { display: none }`, so a
|
|
9
|
+
# styled hidden field renders as an empty box and joins the keyboard tab order
|
|
10
|
+
# in Safari (Chromium's UA rule is !important, hiding the bug there).
|
|
11
|
+
#
|
|
12
|
+
# Forms::Hidden.new(name: "user[token]", id: "user_token", value: "abc123")
|
|
13
|
+
#
|
|
14
|
+
# Same component under both themes (:hidden role) — there are no styling
|
|
15
|
+
# classes for a Plain twin to strip. It takes no positional variants and no
|
|
16
|
+
# error:: a hidden field has no visual or error state.
|
|
17
|
+
class Hidden < Phlex::HTML
|
|
18
|
+
def initialize(name: nil, id: nil, value: nil, **attributes)
|
|
19
|
+
@name = name
|
|
20
|
+
@id = id
|
|
21
|
+
@value = value
|
|
22
|
+
@attributes = attributes
|
|
23
|
+
super()
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def view_template
|
|
27
|
+
input(type: "hidden", name: @name, id: @id, value: @value.to_s, **@attributes)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -9,14 +9,21 @@ module PhlexForms
|
|
|
9
9
|
# the same family, the LAST occurrence wins — matching Tailwind/daisyui
|
|
10
10
|
# intuition (the later class overrides the earlier).
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
12
|
+
# Width utilities (`w-*`) are the one core-Tailwind family this gem injects a
|
|
13
|
+
# default for (DelegatedField's `w-full`), so they conflict the same way: a
|
|
14
|
+
# caller's `w-36` must REPLACE the default, or both land on the element and
|
|
15
|
+
# stylesheet source order — not author intent — decides which applies.
|
|
16
|
+
#
|
|
17
|
+
# We deliberately do NOT depend on tailwind_merge: daisyui modifier families
|
|
18
|
+
# and the width family are the only conflicts that occur on form fields, so
|
|
19
|
+
# tailwind_merge would add a runtime dependency for conflicts this handles.
|
|
20
|
+
# Other non-conflicting utilities (`py-0`, `min-w-32`, ...) pass through in
|
|
21
|
+
# order.
|
|
17
22
|
module ClassMerge
|
|
18
23
|
SIZE = /-(xs|sm|md|lg|xl)\z/
|
|
19
24
|
COLOR = /-(primary|secondary|accent|neutral|info|success|warning|error)\z/
|
|
25
|
+
# Anchored so min-w-*/max-w-* (different CSS properties) stay out of the family.
|
|
26
|
+
WIDTH = /\Aw-/
|
|
20
27
|
|
|
21
28
|
module_function
|
|
22
29
|
|
|
@@ -43,9 +50,12 @@ module PhlexForms
|
|
|
43
50
|
end
|
|
44
51
|
end
|
|
45
52
|
|
|
46
|
-
# A stable bucket key like "input:size" / "select:color", or nil if
|
|
47
|
-
# is not a recognized
|
|
53
|
+
# A stable bucket key like "width" / "input:size" / "select:color", or nil if
|
|
54
|
+
# the token is not a recognized conflicting family. WIDTH is checked first so
|
|
55
|
+
# a `w-*` token can never be mis-bucketed as a daisyui modifier.
|
|
48
56
|
def family_key(token)
|
|
57
|
+
return "width" if WIDTH.match?(token)
|
|
58
|
+
|
|
49
59
|
if (m = token.match(SIZE))
|
|
50
60
|
"#{token[0...m.begin(0)]}:size"
|
|
51
61
|
elsif (m = token.match(COLOR))
|
|
@@ -42,10 +42,13 @@ module PhlexForms
|
|
|
42
42
|
attrs.compact
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
# Merged via ClassMerge so a caller width (`w-36`) REPLACES the default
|
|
46
|
+
# instead of stacking with it (`w-full w-36` leaves the winner to stylesheet
|
|
47
|
+
# source order — that's how admin filter selects went full-width, zazu#2934).
|
|
45
48
|
def width_class
|
|
46
49
|
return @attributes[:class] unless @full_width
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
ClassMerge.merge("w-full", @attributes[:class])
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
# Unstyled variant of binding_attributes for the Plain theme: caller classes
|
data/lib/phlex_forms/theme.rb
CHANGED
|
@@ -4,7 +4,9 @@ module PhlexForms
|
|
|
4
4
|
# A theme maps component roles (:input, :select, :control, ...) to component
|
|
5
5
|
# classes. The binding contract — the leaf initializer signatures
|
|
6
6
|
# (*modifiers, name:, id:, value:, error:, required:, ...) — is the stable
|
|
7
|
-
# interface, so the same form class renders under any theme.
|
|
7
|
+
# interface, so the same form class renders under any theme. The one exception
|
|
8
|
+
# is :hidden, which takes name:/id:/value: only — a hidden field has neither a
|
|
9
|
+
# visual variant nor an error state.
|
|
8
10
|
#
|
|
9
11
|
# Built-ins:
|
|
10
12
|
# Theme.daisy — the DaisyUI-delegating Forms::* leaves (default when the
|
|
@@ -56,7 +58,7 @@ module PhlexForms
|
|
|
56
58
|
textarea: Forms::Textarea, rich_textarea: Forms::RichTextarea,
|
|
57
59
|
checkbox: Forms::Checkbox, toggle: Forms::Toggle, radio: Forms::Radio,
|
|
58
60
|
checkbox_group: Forms::CheckboxGroup,
|
|
59
|
-
file: Forms::FileInput, wrapped_input: Forms::WrappedInput,
|
|
61
|
+
file: Forms::FileInput, wrapped_input: Forms::WrappedInput, hidden: Forms::Hidden,
|
|
60
62
|
control: Forms::FormControl, label: Forms::Label,
|
|
61
63
|
field_error: Forms::FieldError, field_hint: Forms::FieldHint,
|
|
62
64
|
submit: Forms::Submit, row: Forms::Row, group: Forms::Group,
|
|
@@ -74,7 +76,7 @@ module PhlexForms
|
|
|
74
76
|
textarea: Forms::Plain::Textarea, rich_textarea: Forms::Plain::Textarea,
|
|
75
77
|
checkbox: Forms::Plain::Checkbox, toggle: Forms::Plain::Checkbox, radio: Forms::Plain::Radio,
|
|
76
78
|
checkbox_group: Forms::Plain::CheckboxGroup,
|
|
77
|
-
file: Forms::Plain::FileInput, wrapped_input: Forms::Plain::WrappedInput,
|
|
79
|
+
file: Forms::Plain::FileInput, wrapped_input: Forms::Plain::WrappedInput, hidden: Forms::Hidden,
|
|
78
80
|
control: Forms::Plain::Control, label: Forms::Plain::Label,
|
|
79
81
|
field_error: Forms::Plain::FieldError, field_hint: Forms::Plain::FieldHint,
|
|
80
82
|
submit: Forms::Plain::Submit, row: Forms::Plain::Row, group: Forms::Plain::Group,
|
data/lib/phlex_forms/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: phlex-forms
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -128,6 +128,7 @@ files:
|
|
|
128
128
|
- lib/forms/form.rb
|
|
129
129
|
- lib/forms/form_control.rb
|
|
130
130
|
- lib/forms/group.rb
|
|
131
|
+
- lib/forms/hidden.rb
|
|
131
132
|
- lib/forms/input.rb
|
|
132
133
|
- lib/forms/label.rb
|
|
133
134
|
- lib/forms/live.rb
|