phlexi-display 0.0.1 → 0.0.2

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/phlexi/display/base.rb +35 -158
  3. data/lib/phlexi/display/components/base.rb +1 -14
  4. data/lib/phlexi/display/components/concerns/displays_value.rb +54 -0
  5. data/lib/phlexi/display/components/date_time.rb +49 -0
  6. data/lib/phlexi/display/components/{error.rb → description.rb} +5 -5
  7. data/lib/phlexi/display/components/hint.rb +1 -1
  8. data/lib/phlexi/display/components/label.rb +3 -15
  9. data/lib/phlexi/display/components/number.rb +37 -0
  10. data/lib/phlexi/display/components/placeholder.rb +15 -0
  11. data/lib/phlexi/display/components/string.rb +17 -0
  12. data/lib/phlexi/display/components/wrapper.rb +4 -18
  13. data/lib/phlexi/display/field_options/associations.rb +2 -2
  14. data/lib/phlexi/display/field_options/attachments.rb +21 -0
  15. data/lib/phlexi/display/field_options/description.rb +22 -0
  16. data/lib/phlexi/display/field_options/hints.rb +1 -1
  17. data/lib/phlexi/display/field_options/inferred_types.rb +26 -52
  18. data/lib/phlexi/display/field_options/{placeholder.rb → placeholders.rb} +2 -2
  19. data/lib/phlexi/display/field_options/themes.rb +45 -120
  20. data/lib/phlexi/display/structure/dom.rb +7 -27
  21. data/lib/phlexi/display/structure/field_builder.rb +75 -151
  22. data/lib/phlexi/display/structure/field_collection.rb +5 -20
  23. data/lib/phlexi/display/structure/namespace.rb +22 -34
  24. data/lib/phlexi/display/structure/namespace_collection.rb +1 -9
  25. data/lib/phlexi/display/structure/node.rb +9 -3
  26. data/lib/phlexi/display/version.rb +1 -1
  27. data/lib/phlexi/display.rb +0 -1
  28. metadata +11 -31
  29. data/lib/phlexi/display/components/checkbox.rb +0 -48
  30. data/lib/phlexi/display/components/collection_checkboxes.rb +0 -44
  31. data/lib/phlexi/display/components/collection_radio_buttons.rb +0 -35
  32. data/lib/phlexi/display/components/concerns/handles_array_input.rb +0 -21
  33. data/lib/phlexi/display/components/concerns/handles_input.rb +0 -53
  34. data/lib/phlexi/display/components/concerns/has_options.rb +0 -37
  35. data/lib/phlexi/display/components/concerns/submits_form.rb +0 -39
  36. data/lib/phlexi/display/components/file_input.rb +0 -32
  37. data/lib/phlexi/display/components/full_error.rb +0 -21
  38. data/lib/phlexi/display/components/input.rb +0 -84
  39. data/lib/phlexi/display/components/input_array.rb +0 -45
  40. data/lib/phlexi/display/components/radio_button.rb +0 -41
  41. data/lib/phlexi/display/components/select.rb +0 -69
  42. data/lib/phlexi/display/components/submit_button.rb +0 -41
  43. data/lib/phlexi/display/components/textarea.rb +0 -34
  44. data/lib/phlexi/display/field_options/autofocus.rb +0 -18
  45. data/lib/phlexi/display/field_options/collection.rb +0 -54
  46. data/lib/phlexi/display/field_options/disabled.rb +0 -18
  47. data/lib/phlexi/display/field_options/errors.rb +0 -92
  48. data/lib/phlexi/display/field_options/length.rb +0 -53
  49. data/lib/phlexi/display/field_options/limit.rb +0 -66
  50. data/lib/phlexi/display/field_options/min_max.rb +0 -92
  51. data/lib/phlexi/display/field_options/multiple.rb +0 -65
  52. data/lib/phlexi/display/field_options/pattern.rb +0 -38
  53. data/lib/phlexi/display/field_options/readonly.rb +0 -18
  54. data/lib/phlexi/display/field_options/required.rb +0 -37
  55. data/lib/phlexi/display/field_options/validators.rb +0 -48
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Errors
7
- def custom_error(error)
8
- options[:error] = error
9
- self
10
- end
11
-
12
- def error
13
- error_text if has_errors?
14
- end
15
-
16
- def full_error
17
- full_error_text if has_errors?
18
- end
19
-
20
- def has_errors?
21
- object_with_errors? || !object && has_custom_error?
22
- end
23
-
24
- def show_errors?
25
- options[:error] != false
26
- end
27
-
28
- def valid?
29
- !has_errors? && has_value?
30
- end
31
-
32
- protected
33
-
34
- def error_text
35
- text = has_custom_error? ? options[:error] : errors.send(error_method)
36
-
37
- "#{options[:error_prefix]} #{text}".lstrip
38
- end
39
-
40
- def full_error_text
41
- has_custom_error? ? options[:error] : full_errors.send(error_method)
42
- end
43
-
44
- def object_with_errors?
45
- object&.respond_to?(:errors) && errors.present?
46
- end
47
-
48
- def error_method
49
- options[:error_method] || :first
50
- end
51
-
52
- def errors
53
- @errors ||= (errors_on_attribute + errors_on_association).compact
54
- end
55
-
56
- def full_errors
57
- @full_errors ||= (full_errors_on_attribute + full_errors_on_association).compact
58
- end
59
-
60
- def errors_on_attribute
61
- object.errors[key] || []
62
- end
63
-
64
- def full_errors_on_attribute
65
- object.errors.full_messages_for(key)
66
- end
67
-
68
- def errors_on_association
69
- reflection ? object.errors[reflection.name] : []
70
- end
71
-
72
- def full_errors_on_association
73
- reflection ? object.errors.full_messages_for(reflection.name) : []
74
- end
75
-
76
- def has_custom_error?
77
- options[:error].is_a?(String)
78
- end
79
-
80
- # Determines if the associated object is in a valid state
81
- #
82
- # An object is considered valid if it is persisted and has no errors.
83
- #
84
- # @return [Boolean] true if the object is persisted and has no errors, false otherwise
85
- def object_valid?
86
- object.respond_to?(:persisted?) && object.persisted? &&
87
- object.respond_to?(:errors) && !object.errors.empty?
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Length
7
- def minlength(minlength = nil)
8
- if minlength.nil?
9
- options[:minlength] = options.fetch(:minlength) { calculate_minlength }
10
- else
11
- options[:minlength] = minlength
12
- self
13
- end
14
- end
15
-
16
- def maxlength(maxlength = nil)
17
- if maxlength.nil?
18
- options[:maxlength] = options.fetch(:maxlength) { calculate_maxlength }
19
- else
20
- options[:maxlength] = maxlength
21
- self
22
- end
23
- end
24
-
25
- private
26
-
27
- def calculate_minlength
28
- minimum_length_value_from(find_length_validator)
29
- end
30
-
31
- def minimum_length_value_from(length_validator)
32
- if length_validator
33
- length_validator.options[:is] || length_validator.options[:minimum]
34
- end
35
- end
36
-
37
- def calculate_maxlength
38
- maximum_length_value_from(find_length_validator)
39
- end
40
-
41
- def maximum_length_value_from(length_validator)
42
- if length_validator
43
- length_validator.options[:is] || length_validator.options[:maximum]
44
- end
45
- end
46
-
47
- def find_length_validator
48
- find_validator(:length)
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Limit
7
- def limit(limit = nil)
8
- if limit.nil?
9
- options[:limit] = options.fetch(:limit) { calculate_limit }
10
- else
11
- options[:limit] = limit
12
- self
13
- end
14
- end
15
-
16
- private
17
-
18
- def calculate_limit
19
- return unless multiple?
20
-
21
- limit_from_validators = [
22
- limit_from_length_validator,
23
- limit_from_inclusion_validator
24
- ].compact.min
25
-
26
- limit_from_validators || limit_from_db_column
27
- end
28
-
29
- def limit_from_length_validator
30
- length_validator = find_validator(:length)
31
- return unless length_validator
32
-
33
- length_validator.options[:maximum]
34
- end
35
-
36
- def limit_from_inclusion_validator
37
- return unless has_validators?
38
-
39
- inclusion_validator = find_validator(:inclusion)
40
- return unless inclusion_validator
41
-
42
- in_option = inclusion_validator.options[:in]
43
- in_option.is_a?(Array) ? in_option.size : nil
44
- end
45
-
46
- def limit_from_db_column
47
- return unless object.class.respond_to?(:columns_hash)
48
-
49
- column = object.class.columns_hash[key.to_s]
50
- return unless column
51
-
52
- case object.class.connection.adapter_name.downcase
53
- when "postgresql"
54
- if column.array?
55
- # Check if there's a limit on the array size
56
- column.limit
57
- elsif column.type == :string && column.sql_type.include?("[]")
58
- # For string arrays, extract the limit if specified
59
- column.sql_type.match(/\[(\d+)\]/)&.captures&.first&.to_i
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module MinMax
7
- def min(min_value = nil)
8
- if min_value.nil?
9
- options[:min] = options.fetch(:min) { calculate_min }
10
- else
11
- options[:min] = min_value
12
- self
13
- end
14
- end
15
-
16
- def max(max_value = nil)
17
- if max_value.nil?
18
- options[:max] = options.fetch(:max) { calculate_max }
19
- else
20
- options[:max] = max_value
21
- self
22
- end
23
- end
24
-
25
- def step
26
- 1 if min || max
27
- end
28
-
29
- private
30
-
31
- def calculate_min
32
- if (numericality_validator = find_numericality_validator)
33
- get_min_from_validator(numericality_validator)
34
- end
35
- end
36
-
37
- def calculate_max
38
- if (numericality_validator = find_numericality_validator)
39
- get_max_from_validator(numericality_validator)
40
- end
41
- end
42
-
43
- def find_numericality_validator
44
- find_validator(:numericality)
45
- end
46
-
47
- def get_min_from_validator(validator)
48
- options = validator.options
49
- min = if options.key?(:greater_than)
50
- {value: options[:greater_than], exclusive: true}
51
- elsif options.key?(:greater_than_or_equal_to)
52
- {value: options[:greater_than_or_equal_to], exclusive: false}
53
- end
54
- evaluate_and_adjust_min(min)
55
- end
56
-
57
- def get_max_from_validator(validator)
58
- options = validator.options
59
- max = if options.key?(:less_than)
60
- {value: options[:less_than], exclusive: true}
61
- elsif options.key?(:less_than_or_equal_to)
62
- {value: options[:less_than_or_equal_to], exclusive: false}
63
- end
64
- evaluate_and_adjust_max(max)
65
- end
66
-
67
- def evaluate_and_adjust_min(min)
68
- return nil unless min
69
-
70
- value = evaluate_numericality_validator_option(min[:value])
71
- min[:exclusive] ? value + 1 : value
72
- end
73
-
74
- def evaluate_and_adjust_max(max)
75
- return nil unless max
76
-
77
- value = evaluate_numericality_validator_option(max[:value])
78
- max[:exclusive] ? value - 1 : value
79
- end
80
-
81
- def evaluate_numericality_validator_option(option)
82
- case option
83
- when Proc
84
- option.arity.zero? ? option.call : option.call(object)
85
- else
86
- option
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Multiple
7
- def multiple?
8
- options[:multiple] = options.fetch(:multiple) { calculate_multiple_field_value }
9
- end
10
-
11
- def multiple!(multiple = true)
12
- options[:multiple] = multiple
13
- self
14
- end
15
-
16
- private
17
-
18
- def calculate_multiple_field_value
19
- return true if reflection&.macro == :has_many
20
- return true if multiple_field_array_attribute?
21
-
22
- check_multiple_field_from_validators
23
- end
24
-
25
- def multiple_field_array_attribute?
26
- return false unless object.class.respond_to?(:columns_hash)
27
-
28
- column = object.class.columns_hash[key.to_s]
29
- return false unless column
30
-
31
- case object.class.connection.adapter_name.downcase
32
- when "postgresql"
33
- column.array? || (column.type == :string && column.sql_type.include?("[]"))
34
- end # || object.class.attribute_types[key.to_s].is_a?(ActiveRecord::Type::Serialized)
35
- rescue
36
- # Rails.logger.warn("Error checking multiple field array attribute: #{e.message}")
37
- false
38
- end
39
-
40
- def check_multiple_field_from_validators
41
- inclusion_validator = find_validator(:inclusion)
42
- length_validator = find_validator(:length)
43
-
44
- return false unless inclusion_validator || length_validator
45
-
46
- check_multiple_field_inclusion_validator(inclusion_validator) ||
47
- check_multiple_field_length_validator(length_validator)
48
- end
49
-
50
- def check_multiple_field_inclusion_validator(validator)
51
- return false unless validator
52
- in_option = validator.options[:in]
53
- return false unless in_option.is_a?(Array)
54
-
55
- validator.options[:multiple] == true || (multiple_field_array_attribute? && in_option.size > 1)
56
- end
57
-
58
- def check_multiple_field_length_validator(validator)
59
- return false unless validator
60
- validator.options[:maximum].to_i > 1 if validator.options[:maximum]
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Pattern
7
- def pattern(pattern = nil)
8
- if pattern.nil?
9
- options[:pattern] = options.fetch(:pattern) { calculate_pattern }
10
- else
11
- options[:pattern] = pattern
12
- self
13
- end
14
- end
15
-
16
- private
17
-
18
- def calculate_pattern
19
- if (pattern_validator = find_pattern_validator) && (with = pattern_validator.options[:with])
20
- evaluate_format_validator_option(with).source
21
- end
22
- end
23
-
24
- def find_pattern_validator
25
- find_validator(:format)
26
- end
27
-
28
- def evaluate_format_validator_option(option)
29
- if option.respond_to?(:call)
30
- option.call(object)
31
- else
32
- option
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Readonly
7
- def readonly?
8
- options[:readonly] == true
9
- end
10
-
11
- def readonly!(readonly = true)
12
- options[:readonly] = readonly
13
- self
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Required
7
- def required?
8
- options[:required] = options.fetch(:required) { calculate_required }
9
- end
10
-
11
- def required!(required = true)
12
- options[:required] = required
13
- self
14
- end
15
-
16
- private
17
-
18
- def calculate_required
19
- if has_validators?
20
- required_by_validators?
21
- else
22
- required_by_default?
23
- end
24
- end
25
-
26
- def required_by_validators?
27
- (attribute_validators + reflection_validators).any? { |v| v.kind == :presence && valid_validator?(v) }
28
- end
29
-
30
- def required_by_default?
31
- # TODO: get this from configuration
32
- false
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Display
5
- module FieldOptions
6
- module Validators
7
- private
8
-
9
- def has_validators?
10
- @has_validators ||= object.class.respond_to?(:validators_on)
11
- end
12
-
13
- def attribute_validators
14
- object.class.validators_on(key)
15
- end
16
-
17
- def reflection_validators
18
- reflection ? object.class.validators_on(reflection.name) : []
19
- end
20
-
21
- def valid_validator?(validator)
22
- !conditional_validators?(validator) && action_validator_match?(validator)
23
- end
24
-
25
- def conditional_validators?(validator)
26
- validator.options.include?(:if) || validator.options.include?(:unless)
27
- end
28
-
29
- def action_validator_match?(validator)
30
- return true unless validator.options.include?(:on)
31
-
32
- case validator.options[:on]
33
- when :save
34
- true
35
- when :create
36
- !object.persisted?
37
- when :update
38
- object.persisted?
39
- end
40
- end
41
-
42
- def find_validator(kind)
43
- attribute_validators.find { |v| v.kind == kind && valid_validator?(v) } if has_validators?
44
- end
45
- end
46
- end
47
- end
48
- end