phlex-forms 0.3.1 → 0.4.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 +42 -0
- data/README.md +3 -5
- data/lib/forms/choices_select.rb +1 -1
- data/lib/forms/collection_check_box.rb +1 -1
- data/lib/forms/field_error.rb +1 -1
- data/lib/forms/field_hint.rb +1 -1
- data/lib/forms/form.rb +3 -4
- data/lib/forms/form_control.rb +2 -3
- data/lib/forms/rich_textarea.rb +1 -1
- data/lib/forms/row.rb +1 -2
- data/lib/forms/tag_field.rb +1 -1
- data/lib/phlex_forms/configuration.rb +2 -2
- data/lib/phlex_forms/delegated_field.rb +3 -4
- data/lib/phlex_forms/theme.rb +1 -8
- data/lib/phlex_forms/version.rb +1 -1
- data/lib/phlex_forms.rb +2 -9
- metadata +15 -2
- data/lib/phlex_forms/class_merge.rb +0 -66
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26a87406065dfe0b6d5b023949661d89548c3ad6379af9d0e4d74c4162f49070
|
|
4
|
+
data.tar.gz: b36430b1faf88ad5095a358709bce31a72869c40619dc527bc3e04be10450c0f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f9e5a95dfea504c6b487c23a0b5683a4a68391b4e07ff33192b548a40a5b7eff3a0562e0af1097a20bbeca3762017254fe626fb1fe7079408996815f8b1d7a71
|
|
7
|
+
data.tar.gz: 1ae2b903bfe9057f1705b3d3a6e788c16acf1c4d837c0bdbd723434aca71c45432d194ebf638ce17c14d597826751a6c4bb124e92f02e7b3d01fdf29ac6bbf34
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Upgrading to 0.4
|
|
11
|
+
|
|
12
|
+
phlex-forms now depends on **daisyui `~> 2.0`** and merges every default +
|
|
13
|
+
caller `class:` through `DaisyUI::ClassMerge` (a port of tailwind_merge 1.5.6
|
|
14
|
+
plus daisyUI's modifier groups). `PhlexForms::ClassMerge` is gone.
|
|
15
|
+
|
|
16
|
+
- **Bundle daisyui 2.** It's a hard dependency now, so a `gem "daisyui", "~> 1.x"`
|
|
17
|
+
pin in your Gemfile must move to 2.x (or be dropped).
|
|
18
|
+
- **Register your custom Tailwind utilities.** The old merger only knew daisy
|
|
19
|
+
sizes/colors and `w-*`, and passed everything else through. The new one
|
|
20
|
+
classifies every utility, so an unregistered custom one can be dropped as a
|
|
21
|
+
conflict. For example, a `text-h1` you pass next to `FieldError`'s
|
|
22
|
+
`text-error` reads as a colour:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# config/initializers/daisy_ui.rb
|
|
26
|
+
DaisyUI.configure do |config|
|
|
27
|
+
config.class_merge.utility("text-h1", like: "text-lg")
|
|
28
|
+
end
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- **`CollectionCheckBox` merges a caller `class:` instead of replacing its
|
|
32
|
+
base class.** `class: "checkbox-primary"` now renders `checkbox
|
|
33
|
+
checkbox-primary` (it used to drop `checkbox`). A caller who used `class:` to
|
|
34
|
+
swap the base class entirely (`class: "toggle"`) now gets both classes.
|
|
35
|
+
- **More conflicts resolve now.** A caller's `mt-4` / `text-xs` replaces a
|
|
36
|
+
component's default `mt-1` / `text-sm` instead of stacking beside it.
|
|
37
|
+
- **Daisy leaves lean on daisyui's own merge.** Input, Select, Textarea and the
|
|
38
|
+
other delegated leaves hand `class:` to the daisyui component, so
|
|
39
|
+
`DaisyUI.configure { |c| c.class_merge.enabled = false }` applies to them too.
|
|
40
|
+
The components that render plain HTML (FieldHint, FieldError, Row, Form,
|
|
41
|
+
FormControl, TagField, ChoicesSelect) merge through `DaisyUI::ClassMerge.merge`
|
|
42
|
+
directly, which that switch doesn't affect.
|
|
43
|
+
|
|
44
|
+
### Removed
|
|
45
|
+
|
|
46
|
+
- **`PhlexForms::ClassMerge`**: use `DaisyUI::ClassMerge.merge`.
|
|
47
|
+
- **The daisyui soft-dependency path.** `require "phlex_forms"` loads daisyui
|
|
48
|
+
unconditionally, the daisy theme is always the default, and `Theme.daisy` no
|
|
49
|
+
longer raises `FeatureUnavailable`. The Plain theme is unchanged and still
|
|
50
|
+
emits zero daisy classes.
|
|
51
|
+
|
|
10
52
|
### Fixed
|
|
11
53
|
|
|
12
54
|
- **`rich_textarea` forwards its block into `<lexxy-editor>`**: Lexxy configures
|
data/README.md
CHANGED
|
@@ -42,7 +42,6 @@ end
|
|
|
42
42
|
```ruby
|
|
43
43
|
# Gemfile
|
|
44
44
|
gem "phlex-forms"
|
|
45
|
-
gem "daisyui" # optional — the daisy theme; omit for plain semantic HTML
|
|
46
45
|
gem "phlex-reactive" # optional — the `live` server-truth validation
|
|
47
46
|
```
|
|
48
47
|
|
|
@@ -254,11 +253,10 @@ f.field(:search).wrapped_input(:primary) do
|
|
|
254
253
|
end
|
|
255
254
|
```
|
|
256
255
|
|
|
257
|
-
## Themes — using phlex-forms without
|
|
256
|
+
## Themes — using phlex-forms without daisyUI styling
|
|
258
257
|
|
|
259
|
-
Every component resolves through a theme (a role → component-class map).
|
|
260
|
-
the
|
|
261
|
-
demand — the **Plain theme** renders bare semantic HTML: the same binding
|
|
258
|
+
Every component resolves through a theme (a role → component-class map). The
|
|
259
|
+
daisy theme is the default. On demand, the **Plain theme** renders bare semantic HTML: the same binding
|
|
262
260
|
(names, ids, values, required, errors), variants accepted and ignored, no
|
|
263
261
|
styling classes, and stable hooks (`aria-invalid`, `role="alert"`,
|
|
264
262
|
`data-field-error`, `data-field-hint`, `data-form-row`) for your own CSS.
|
data/lib/forms/choices_select.rb
CHANGED
|
@@ -44,7 +44,7 @@ module Forms
|
|
|
44
44
|
a = {
|
|
45
45
|
name: select_name,
|
|
46
46
|
id: @id,
|
|
47
|
-
class:
|
|
47
|
+
class: DaisyUI::ClassMerge.merge("choices-select w-full", @options[:class]),
|
|
48
48
|
data: stimulus_data,
|
|
49
49
|
**@options.except(:class, :value, :data)
|
|
50
50
|
}
|
data/lib/forms/field_error.rb
CHANGED
data/lib/forms/field_hint.rb
CHANGED
data/lib/forms/form.rb
CHANGED
|
@@ -224,10 +224,9 @@ module Forms
|
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
def form_classes
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
PhlexForms::ClassMerge.merge(classes.join(" "), @options[:class]).presence
|
|
227
|
+
spaced = "space-y-4" if @base_modifiers.include?(:spaced)
|
|
228
|
+
spacious = "space-y-6" if @base_modifiers.include?(:spacious)
|
|
229
|
+
DaisyUI::ClassMerge.merge(spaced, spacious, @options[:class]).presence
|
|
231
230
|
end
|
|
232
231
|
|
|
233
232
|
def authenticity_token_field
|
data/lib/forms/form_control.rb
CHANGED
|
@@ -40,9 +40,8 @@ module Forms
|
|
|
40
40
|
private
|
|
41
41
|
|
|
42
42
|
def control_classes
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
PhlexForms::ClassMerge.merge(base.join(" "), @options[:class])
|
|
43
|
+
horizontal = "flex flex-row items-center gap-4" if @modifiers.include?(:horizontal)
|
|
44
|
+
DaisyUI::ClassMerge.merge("form-control w-full", horizontal, @options[:class])
|
|
46
45
|
end
|
|
47
46
|
end
|
|
48
47
|
end
|
data/lib/forms/rich_textarea.rb
CHANGED
data/lib/forms/row.rb
CHANGED
|
@@ -27,8 +27,7 @@ module Forms
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def row_classes
|
|
30
|
-
|
|
31
|
-
PhlexForms::ClassMerge.merge(base, @options[:class])
|
|
30
|
+
DaisyUI::ClassMerge.merge("grid grid-cols-1 gap-4", COLUMN_CLASSES[@columns], @options[:class])
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
end
|
data/lib/forms/tag_field.rb
CHANGED
|
@@ -135,6 +135,6 @@ module Forms
|
|
|
135
135
|
def option_classes = nil
|
|
136
136
|
def chip_classes = "badge badge-primary gap-1"
|
|
137
137
|
def remove_classes = "cursor-pointer"
|
|
138
|
-
def input_classes =
|
|
138
|
+
def input_classes = DaisyUI::ClassMerge.merge("input w-full", @attributes[:class])
|
|
139
139
|
end
|
|
140
140
|
end
|
|
@@ -51,11 +51,11 @@ module PhlexForms
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# The default theme: :daisy, :plain, or a PhlexForms::Theme instance.
|
|
54
|
-
# Defaults to daisy
|
|
54
|
+
# Defaults to daisy.
|
|
55
55
|
attr_writer :theme
|
|
56
56
|
|
|
57
57
|
def theme
|
|
58
|
-
@theme ||=
|
|
58
|
+
@theme ||= Theme.daisy
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def infer_from_model
|
|
@@ -42,13 +42,12 @@ module PhlexForms
|
|
|
42
42
|
attrs.compact
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
# source order — that's how admin filter selects went full-width, zazu#2934).
|
|
45
|
+
# Handed to the daisyui component as parts: its class merge lets a caller
|
|
46
|
+
# width (`w-36`) REPLACE the default instead of stacking with it (zazu#2934).
|
|
48
47
|
def width_class
|
|
49
48
|
return @attributes[:class] unless @full_width
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
["w-full", *@attributes[:class]]
|
|
52
51
|
end
|
|
53
52
|
|
|
54
53
|
# Unstyled variant of binding_attributes for the Plain theme: caller classes
|
data/lib/phlex_forms/theme.rb
CHANGED
|
@@ -9,8 +9,7 @@ module PhlexForms
|
|
|
9
9
|
# visual variant nor an error state.
|
|
10
10
|
#
|
|
11
11
|
# Built-ins:
|
|
12
|
-
# Theme.daisy — the DaisyUI-delegating Forms::* leaves (default
|
|
13
|
-
# daisyui gem is loaded)
|
|
12
|
+
# Theme.daisy — the DaisyUI-delegating Forms::* leaves (the default)
|
|
14
13
|
# Theme.plain — bare semantic HTML (Forms::Plain::*): variants accepted and
|
|
15
14
|
# ignored, zero styling classes, aria/data hooks only
|
|
16
15
|
#
|
|
@@ -47,12 +46,6 @@ module PhlexForms
|
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
def daisy
|
|
50
|
-
unless defined?(DaisyUI)
|
|
51
|
-
raise PhlexForms::FeatureUnavailable,
|
|
52
|
-
"the daisy theme requires the daisyui gem. Add `gem \"daisyui\"` to your " \
|
|
53
|
-
"Gemfile, or use the plain theme."
|
|
54
|
-
end
|
|
55
|
-
|
|
56
49
|
@daisy ||= new({
|
|
57
50
|
input: Forms::Input, select: Forms::Select, choices_select: Forms::ChoicesSelect,
|
|
58
51
|
textarea: Forms::Textarea, rich_textarea: Forms::RichTextarea,
|
data/lib/phlex_forms/version.rb
CHANGED
data/lib/phlex_forms.rb
CHANGED
|
@@ -7,14 +7,7 @@ require "active_support/core_ext/string" # underscore/pluralize/humanize (scope/
|
|
|
7
7
|
require "phlex"
|
|
8
8
|
require "glyphs"
|
|
9
9
|
require "zeitwerk"
|
|
10
|
-
|
|
11
|
-
begin
|
|
12
|
-
require "daisy_ui"
|
|
13
|
-
rescue LoadError
|
|
14
|
-
# daisyui is a soft dependency: without it the Plain theme is the default.
|
|
15
|
-
# The daisy leaf components only reference DaisyUI inside view_template, so
|
|
16
|
-
# they load fine — they just must not be rendered (Theme.daisy raises).
|
|
17
|
-
end
|
|
10
|
+
require "daisy_ui"
|
|
18
11
|
|
|
19
12
|
begin
|
|
20
13
|
require "phlex/reactive"
|
|
@@ -75,7 +68,7 @@ loader.inflector.inflect(
|
|
|
75
68
|
)
|
|
76
69
|
|
|
77
70
|
# Two sibling (non-nested) autoload roots:
|
|
78
|
-
# lib/phlex_forms -> PhlexForms:: (gem internals: config,
|
|
71
|
+
# lib/phlex_forms -> PhlexForms:: (gem internals: config, inference, theme, ...)
|
|
79
72
|
# lib/forms -> Forms:: (the component kit)
|
|
80
73
|
# Keeping them as separate top-level dirs avoids the ambiguity of nesting one
|
|
81
74
|
# namespace root inside another.
|
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.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -29,6 +29,20 @@ dependencies:
|
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '9'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: daisyui
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '2.0'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '2.0'
|
|
32
46
|
- !ruby/object:Gem::Dependency
|
|
33
47
|
name: glyphs
|
|
34
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -168,7 +182,6 @@ files:
|
|
|
168
182
|
- lib/phlex-forms.rb
|
|
169
183
|
- lib/phlex_forms.rb
|
|
170
184
|
- lib/phlex_forms/builder.rb
|
|
171
|
-
- lib/phlex_forms/class_merge.rb
|
|
172
185
|
- lib/phlex_forms/configuration.rb
|
|
173
186
|
- lib/phlex_forms/delegated_field.rb
|
|
174
187
|
- lib/phlex_forms/engine.rb
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PhlexForms
|
|
4
|
-
# Class-string merging for phlex-forms components.
|
|
5
|
-
#
|
|
6
|
-
# DaisyUI component-class families are mutually exclusive: an element can't be
|
|
7
|
-
# both `input-sm` and `input-lg`, or both `input-primary` and `input-error`.
|
|
8
|
-
# When a component's default classes and a caller's `class:` override both name
|
|
9
|
-
# the same family, the LAST occurrence wins — matching Tailwind/daisyui
|
|
10
|
-
# intuition (the later class overrides the earlier).
|
|
11
|
-
#
|
|
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.
|
|
22
|
-
module ClassMerge
|
|
23
|
-
SIZE = /-(xs|sm|md|lg|xl)\z/
|
|
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-/
|
|
27
|
-
|
|
28
|
-
module_function
|
|
29
|
-
|
|
30
|
-
# Merge any number of class strings/nil into one deduped string. Preserves
|
|
31
|
-
# order; within a daisyui size/color family only the last token survives.
|
|
32
|
-
def merge(*parts)
|
|
33
|
-
tokens = parts.flat_map { |p| p.to_s.split }.reject(&:empty?)
|
|
34
|
-
dedupe_daisyui_families(tokens).join(" ")
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# For each (component-prefix, family) pair, keep only the last token.
|
|
38
|
-
def dedupe_daisyui_families(tokens)
|
|
39
|
-
last_index = {}
|
|
40
|
-
tokens.each_with_index do |tok, idx|
|
|
41
|
-
key = family_key(tok)
|
|
42
|
-
last_index[key] = idx if key
|
|
43
|
-
end
|
|
44
|
-
tokens.each_with_index.filter_map do |tok, idx|
|
|
45
|
-
key = family_key(tok)
|
|
46
|
-
next tok if key.nil? # not a daisyui family token — keep
|
|
47
|
-
next tok if last_index[key] == idx # last in its family — keep
|
|
48
|
-
|
|
49
|
-
nil # earlier duplicate in the family — drop
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
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.
|
|
56
|
-
def family_key(token)
|
|
57
|
-
return "width" if WIDTH.match?(token)
|
|
58
|
-
|
|
59
|
-
if (m = token.match(SIZE))
|
|
60
|
-
"#{token[0...m.begin(0)]}:size"
|
|
61
|
-
elsif (m = token.match(COLOR))
|
|
62
|
-
"#{token[0...m.begin(0)]}:color"
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|