lesli_view 1.1.2 → 1.1.4

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/lesli_view/charts/bar.rb +10 -0
  3. data/lib/lesli_view/charts/general.html.erb +38 -52
  4. data/lib/lesli_view/charts/general.rb +69 -30
  5. data/lib/lesli_view/charts/line.rb +16 -0
  6. data/lib/lesli_view/components/header.html.erb +48 -23
  7. data/lib/lesli_view/components/header.rb +35 -2
  8. data/lib/lesli_view/components/tabs.html.erb +59 -26
  9. data/lib/lesli_view/components/tabs.rb +7 -7
  10. data/lib/lesli_view/components/timeline.html.erb +28 -25
  11. data/lib/lesli_view/components/toolbar.css +52 -0
  12. data/lib/lesli_view/components/toolbar.html.erb +36 -21
  13. data/lib/lesli_view/components/toolbar.rb +41 -4
  14. data/lib/lesli_view/elements/avatar.html.erb +3 -3
  15. data/lib/lesli_view/elements/avatar.rb +8 -8
  16. data/lib/lesli_view/elements/button.css +357 -0
  17. data/lib/lesli_view/elements/button.html.erb +15 -12
  18. data/lib/lesli_view/elements/button.rb +74 -34
  19. data/lib/lesli_view/elements/empty.html.erb +31 -6
  20. data/lib/lesli_view/elements/empty.rb +8 -1
  21. data/lib/lesli_view/elements/table-chart.html.erb +42 -0
  22. data/lib/lesli_view/elements/table.css +91 -0
  23. data/lib/lesli_view/elements/table.html.erb +24 -21
  24. data/lib/lesli_view/elements/table.rb +67 -17
  25. data/lib/lesli_view/forms/builder.rb +16 -3
  26. data/lib/lesli_view/forms/builder_horizontal.rb +34 -10
  27. data/lib/lesli_view/forms/fields.rb +103 -70
  28. data/lib/lesli_view/forms/fieldset.rb +3 -3
  29. data/lib/lesli_view/forms/form.css +171 -0
  30. data/lib/lesli_view/forms/form.scss +2 -54
  31. data/lib/lesli_view/forms/inputs.rb +27 -15
  32. data/lib/lesli_view/items/activities.html.erb +4 -6
  33. data/lib/lesli_view/items/discussion.html.erb +6 -5
  34. data/lib/lesli_view/items/discussions.html.erb +8 -6
  35. data/lib/lesli_view/items/task.html.erb +16 -11
  36. data/lib/lesli_view/items/tasks.html.erb +8 -13
  37. data/lib/lesli_view/layout/container.html.erb +8 -2
  38. data/lib/lesli_view/partials/engine_spec.html.erb +28 -41
  39. data/lib/lesli_view/version.rb +2 -2
  40. data/lib/lesli_view/widgets/calendar.html.erb +42 -133
  41. data/lib/lesli_view/widgets/calendar.rb +77 -3
  42. data/lib/lesli_view/widgets/chart.html.erb +25 -26
  43. data/lib/lesli_view/widgets/chart.rb +46 -3
  44. data/lib/lesli_view/widgets/count.html.erb +17 -15
  45. data/lib/lesli_view/widgets/count.rb +13 -1
  46. data/lib/lesli_view/widgets/date.html.erb +23 -21
  47. data/lib/lesli_view/widgets/date.rb +27 -2
  48. data/lib/lesli_view/widgets/weather.html.erb +40 -38
  49. data/lib/lesli_view/widgets/weather.rb +41 -2
  50. data/readme.md +185 -29
  51. metadata +6 -10
  52. data/lib/lesli_view/components/header.scss +0 -69
  53. data/lib/lesli_view/components/tabs.scss +0 -49
  54. data/lib/lesli_view/components/tabs_spec.rb +0 -0
  55. data/lib/lesli_view/components/timeline.scss +0 -216
  56. data/lib/lesli_view/components/toolbar.scss +0 -54
  57. data/lib/lesli_view/elements/avatar.scss +0 -50
  58. data/lib/lesli_view/elements/table.scss +0 -153
  59. data/lib/lesli_view/items/activities.scss +0 -39
  60. data/lib/lesli_view/items/discussions.scss +0 -47
@@ -1,67 +1,113 @@
1
1
  module LesliView
2
2
  module Forms
3
3
  module Fields
4
- def field_control(attribute, label: nil, message:nil, category:nil, icon:nil, horizontal: false)
5
- field_control_text(attribute, label:label, message:message, category:category, icon:icon, horizontal:horizontal)
4
+ def field_control(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
5
+ field_control_text(attribute, label: label, message: message, category: category, icon: icon, horizontal: horizontal, **options)
6
6
  end
7
7
 
8
- def field_control_checkbox(attribute, label: nil, message:nil, category:nil, icon:nil, horizontal: false)
8
+ def field_control_checkbox(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
9
+ label_text = label.presence || attribute.to_s.humanize
10
+ checkbox_html = check_box(attribute, options, true, false)
11
+ control_html = @template.content_tag(:label, class: "lesli-form-checkbox-label") do
12
+ @template.safe_join([
13
+ checkbox_html,
14
+ @template.content_tag(:span, label_text)
15
+ ])
16
+ end
17
+
18
+ field_control_builder(
19
+ control_html: control_html,
20
+ message_text: message,
21
+ category: category,
22
+ horizontal: horizontal
23
+ )
24
+ end
25
+
26
+ def field_control_password(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
9
27
  label_html = label(attribute, label)
10
- text_field_html = check_box(attribute, {}, true, false)
28
+ control_html = password_field(attribute, options)
11
29
 
12
30
  field_control_builder(
13
31
  label_html: label_html,
14
- control_html: text_field_html,
32
+ control_html: control_html,
33
+ message_text: message,
34
+ category: category,
35
+ icon: icon,
15
36
  horizontal: horizontal
16
37
  )
17
38
  end
18
39
 
19
- def field_control_text(attribute, label: nil, message:nil, category:nil, icon:nil, horizontal: false)
40
+ def field_control_text(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
20
41
  label_html = label(attribute, label)
21
- text_field_html = text_field(attribute)
42
+ control_html = text_field(attribute, options)
22
43
 
23
44
  field_control_builder(
24
45
  label_html: label_html,
25
- control_html: text_field_html,
46
+ control_html: control_html,
47
+ message_text: message,
48
+ category: category,
49
+ icon: icon,
26
50
  horizontal: horizontal
27
51
  )
28
52
  end
29
53
 
30
- def field_control_email(attribute, label: nil, message:nil, category:nil, icon:nil, horizontal: false)
54
+ def field_control_email(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
31
55
  label_html = label(attribute, label)
32
- control_html = email_field(attribute)
56
+ control_html = email_field(attribute, options)
33
57
 
34
58
  field_control_builder(
35
59
  label_html: label_html,
36
60
  control_html: control_html,
61
+ message_text: message,
62
+ category: category,
37
63
  horizontal: horizontal,
38
- icon:icon
64
+ icon: icon
39
65
  )
40
66
  end
41
67
 
42
- def field_control_select(attribute, choices, label: nil, message:nil, category:nil, icon:nil, horizontal: false, humanize:true)
43
- choices = choices.map { |k, v| [k.humanize.capitalize, v] } if humanize
44
- value = @object.send(attribute)
68
+ def field_control_select(attribute, choices, label: nil, message: nil, category: nil, icon: nil, horizontal: false, humanize: true, options: {}, html_options: {})
69
+ choices = choices.map { |text, value| [text.to_s.humanize, value] } if humanize
45
70
  label_html = label(attribute, label)
46
- select_html = select(attribute, choices, {}, { value: value })
71
+ select_html = select(attribute, choices, options, html_options)
47
72
 
48
73
  field_control_builder(
49
74
  label_html: label_html,
50
- control_html: @template.content_tag(:div, select_html, class: "select is-fullwidth"),
75
+ control_html: @template.content_tag(:div, select_html, class: "lesli-form-select-wrapper"),
76
+ message_text: message,
77
+ category: category,
78
+ icon: icon,
51
79
  horizontal: horizontal
52
80
  )
53
81
  end
54
82
 
55
- def field_control_textarea(attribute, label:nil, message:nil, category:nil, icon:nil, horizontal: false)
56
-
57
- label_html = label == false ? '' : label(attribute, label)
58
- control_html = rich_textarea(attribute)
83
+ def field_control_textarea(attribute, label: nil, message: nil, category: nil, icon: nil, horizontal: false, **options)
84
+ label_html = label == false ? nil : label(attribute, label)
85
+ control_html = rich_textarea(attribute, options)
59
86
 
60
87
  field_control_builder(
61
88
  label_html: label_html,
62
89
  control_html: control_html,
90
+ message_text: message,
91
+ category: category,
63
92
  horizontal: horizontal,
64
- icon:icon
93
+ icon: icon
94
+ )
95
+ end
96
+
97
+ # Backward-compatible shorthand used by older Lesli forms.
98
+ def field_textarea(attribute, **options)
99
+ field_control_textarea(attribute, **options)
100
+ end
101
+
102
+ def field_select(attribute, choices, options = {}, html_options = {}, label: nil, humanize: true, **field_options)
103
+ field_control_select(
104
+ attribute,
105
+ choices,
106
+ label: label,
107
+ humanize: humanize,
108
+ options: options,
109
+ html_options: html_options,
110
+ **field_options
65
111
  )
66
112
  end
67
113
 
@@ -70,75 +116,62 @@ module LesliView
70
116
  field_control_builder(control_html: submit_html, horizontal: horizontal)
71
117
  end
72
118
 
73
- def field_control_button(value = nil, options = {}, category:"primary", icon:nil, type:"submit", horizontal: false)
74
- # Merge user-provided classes with default button classes
75
- button_classes = ["button", "is-#{category}"]
119
+ def field_control_button(value = nil, options = {}, category: "primary", icon: nil, type: "submit", horizontal: false)
120
+ options = options.symbolize_keys
121
+ button_classes = merge_css_classes("lesli-form-button", css_category(category), options.delete(:class))
76
122
 
77
- button_html = @template.content_tag(:button, class: button_classes, type: type, **options.except(:class)) do
78
- html = "".html_safe
123
+ button_html = @template.content_tag(:button, class: button_classes, type: type, **options) do
124
+ content = []
79
125
  if icon.present?
80
- html << @template.content_tag(:span, class: "icon") do
126
+ content << @template.content_tag(:span, class: "lesli-form-button-icon", aria: { hidden: true }) do
81
127
  @template.content_tag(:span, icon, class: "material-symbols")
82
128
  end
83
129
  end
84
- html << @template.content_tag(:span, value) if value.present?
85
- html
130
+ content << @template.content_tag(:span, value) if value.present?
131
+ @template.safe_join(content)
86
132
  end
87
- field_control_builder(control_html: button_html, icon:nil, horizontal: horizontal)
133
+ field_control_builder(control_html: button_html, horizontal: horizontal)
88
134
  end
89
135
 
90
136
  def field_control_builder(
91
- label_html:nil,
92
- control_html:nil,
93
- message_text:nil,
94
- horizontal:false,
95
- category:nil,
96
- icon:nil,
137
+ label_html: nil,
138
+ control_html: nil,
139
+ message_text: nil,
140
+ horizontal: false,
141
+ category: nil,
142
+ icon: nil,
97
143
  &block
98
144
  )
99
-
100
- icon_left = icon
101
- icon_right = nil
102
-
103
- # Conditionally add 'is-horizontal' if horizontal is true
104
- field_classes = ['field']
105
- field_classes << 'is-horizontal' if horizontal
106
-
107
- control_classes = ['control']
108
- control_classes << 'has-icons-left' if icon_left
109
- control_classes << 'has-icons-right' if icon_right
110
-
111
- help_class = ""
112
-
113
- @template.content_tag(:div, class: 'lesli-form-field mb-3') do
114
- @template.content_tag(:div, class: field_classes.join(' ')) do
115
- @template.content_tag(:div, label_html, class: 'field-label is-normal mb-1') +
116
- @template.content_tag(:div, class: 'field-body') do
117
- @template.content_tag(:div, class: 'field') do
118
- control_html = @template.content_tag(:div, class: control_classes.join(' ')) do
119
- content = ''.html_safe
120
- content << (block_given? ? @template.capture(&block) : control_html)
121
- content << icon_html(icon_left, 'left') if icon_left
122
- content << icon_html(icon_right, 'right') if icon_right
123
- content
124
- end
125
- control_html + @template.content_tag(:p, message_text, class: "help #{css_category(category)}")
126
- end
145
+ field_classes = merge_css_classes("lesli-form-field", horizontal && "is-horizontal", css_category(category))
146
+ control_classes = merge_css_classes("lesli-form-control", icon.present? && "has-icon")
147
+ captured_control = block_given? ? @template.capture(&block) : control_html
148
+
149
+ @template.content_tag(:div, class: field_classes) do
150
+ content = []
151
+ content << @template.content_tag(:div, label_html, class: "lesli-form-label-wrapper") if label_html.present?
152
+ content << @template.content_tag(:div, class: "lesli-form-field-body") do
153
+ body = []
154
+ body << @template.content_tag(:div, class: control_classes) do
155
+ @template.safe_join([captured_control, icon_html(icon)].compact)
127
156
  end
157
+ if message_text.present?
158
+ body << @template.content_tag(:p, message_text, class: merge_css_classes("lesli-form-help", css_category(category)))
159
+ end
160
+ @template.safe_join(body)
128
161
  end
162
+ @template.safe_join(content)
129
163
  end
130
164
  end
131
165
 
132
166
  private
133
167
 
134
- def icon_html(icon_class, position)
135
- return ''.html_safe unless icon_class
168
+ def icon_html(icon_name)
169
+ return unless icon_name.present?
136
170
 
137
- @template.content_tag(:span, class: "icon is-small is-#{position}") do
138
- #@template.content_tag(:i, '', class: icon_class)
139
- @template.content_tag(:span, icon_class, class: "material-symbols-outlined")
171
+ @template.content_tag(:span, class: "lesli-form-icon", aria: { hidden: true }) do
172
+ @template.content_tag(:span, icon_name, class: "material-symbols-outlined")
140
173
  end
141
- end
174
+ end
142
175
  end
143
176
  end
144
177
  end
@@ -2,11 +2,11 @@ module LesliView
2
2
  module Forms
3
3
  module Fieldset
4
4
  def fieldset(legend = "", options = {}, category: nil, &block)
5
- options[:class] = ["lesli-form-fieldset", "box", "pr-6", "is-#{category}"]
6
- options[:class].push("pt-5") unless legend.present?
5
+ options = options.symbolize_keys
6
+ options[:class] = merge_css_classes("lesli-form-fieldset", css_category(category), options[:class])
7
7
 
8
8
  @template.content_tag(:fieldset, options) do
9
- legend_html = legend.present? ? @template.content_tag(:h5, legend, class: ["is-size-5", "mb-5", "ml-2"]) : nil
9
+ legend_html = legend.present? ? @template.content_tag(:legend, legend, class: "lesli-form-legend") : nil
10
10
  @template.safe_join([legend_html, @template.capture(&block)].compact)
11
11
  end
12
12
  end
@@ -0,0 +1,171 @@
1
+ /* Tailwind styles for LesliView::Forms builders. */
2
+
3
+ @layer components {
4
+ .lesli-form-field {
5
+ @apply mb-4;
6
+ }
7
+
8
+ .lesli-form-label-wrapper {
9
+ @apply mb-2;
10
+ }
11
+
12
+ .lesli-form-label {
13
+ @apply block text-sm font-medium leading-5 text-slate-700;
14
+ }
15
+
16
+ .lesli-form-field-body {
17
+ @apply min-w-0;
18
+ }
19
+
20
+ .lesli-form-control {
21
+ @apply relative;
22
+ }
23
+
24
+ .lesli-form-input,
25
+ .lesli-form-select,
26
+ .lesli-form-control textarea,
27
+ .lesli-form-control trix-editor {
28
+ @apply block w-full rounded-xl border border-slate-300 bg-white px-3.5 py-2.5 text-sm text-slate-900 shadow-sm outline-none transition placeholder:text-slate-400 hover:border-slate-400 focus:border-sky-500 focus:ring-4 focus:ring-sky-500/10 disabled:cursor-not-allowed disabled:bg-slate-100 disabled:text-slate-500 disabled:opacity-75;
29
+ }
30
+
31
+ .lesli-form-input,
32
+ .lesli-form-select {
33
+ @apply h-11;
34
+ }
35
+
36
+ .lesli-form-control textarea,
37
+ .lesli-form-control trix-editor {
38
+ @apply min-h-32 resize-y;
39
+ }
40
+
41
+ .lesli-form-select-wrapper {
42
+ @apply relative;
43
+ }
44
+
45
+ .lesli-form-select {
46
+ @apply cursor-pointer appearance-none pr-10;
47
+ }
48
+
49
+ .lesli-form-select-wrapper::after {
50
+ @apply pointer-events-none absolute right-3.5 top-1/2 h-2 w-2 -translate-y-2 rotate-45 border-b-2 border-r-2 border-slate-400 content-[''];
51
+ }
52
+
53
+ .lesli-form-checkbox {
54
+ @apply h-4 w-4 cursor-pointer rounded border-slate-300 accent-sky-600 focus:ring-2 focus:ring-sky-500/30 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
55
+ }
56
+
57
+ .lesli-form-checkbox-label {
58
+ @apply inline-flex cursor-pointer items-center gap-2.5 text-sm text-slate-600;
59
+ }
60
+
61
+ .lesli-form-control.has-icon .lesli-form-input,
62
+ .lesli-form-control.has-icon .lesli-form-select {
63
+ @apply pl-11;
64
+ }
65
+
66
+ .lesli-form-icon {
67
+ @apply pointer-events-none absolute left-3.5 top-1/2 inline-flex h-5 w-5 -translate-y-1/2 items-center justify-center text-slate-400;
68
+ }
69
+
70
+ .lesli-form-icon .material-symbols-outlined {
71
+ @apply text-xl leading-none;
72
+ }
73
+
74
+ .lesli-form-help {
75
+ @apply mt-2 text-sm leading-5 text-slate-500;
76
+ }
77
+
78
+ .lesli-form-field.is-danger .lesli-form-input,
79
+ .lesli-form-field.is-danger .lesli-form-select,
80
+ .lesli-form-field.is-danger textarea,
81
+ .lesli-form-field.is-danger trix-editor {
82
+ @apply border-rose-400 focus:border-rose-500 focus:ring-rose-500/10;
83
+ }
84
+
85
+ .lesli-form-help.is-danger {
86
+ @apply text-rose-700;
87
+ }
88
+
89
+ .lesli-form-help.is-warning {
90
+ @apply text-amber-700;
91
+ }
92
+
93
+ .lesli-form-help.is-success {
94
+ @apply text-emerald-700;
95
+ }
96
+
97
+ .lesli-form-help.is-info {
98
+ @apply text-sky-700;
99
+ }
100
+
101
+ .lesli-form-button {
102
+ @apply inline-flex h-11 cursor-pointer items-center justify-center gap-2 rounded-xl border border-transparent px-4 text-sm font-semibold shadow-sm transition focus:outline-none focus:ring-4 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50;
103
+ }
104
+
105
+ .lesli-form-button.is-primary,
106
+ .lesli-form-button.is-info {
107
+ @apply bg-sky-600 text-white hover:bg-sky-700 focus:ring-sky-500/20;
108
+ }
109
+
110
+ .lesli-form-button.is-success {
111
+ @apply bg-emerald-600 text-white hover:bg-emerald-700 focus:ring-emerald-500/20;
112
+ }
113
+
114
+ .lesli-form-button.is-warning {
115
+ @apply bg-amber-500 text-amber-950 hover:bg-amber-600 focus:ring-amber-500/20;
116
+ }
117
+
118
+ .lesli-form-button.is-danger {
119
+ @apply bg-rose-600 text-white hover:bg-rose-700 focus:ring-rose-500/20;
120
+ }
121
+
122
+ .lesli-form-button.is-fullwidth {
123
+ @apply w-full;
124
+ }
125
+
126
+ .lesli-form-button-icon {
127
+ @apply inline-flex h-5 w-5 items-center justify-center;
128
+ }
129
+
130
+ .lesli-form-button-icon .material-symbols {
131
+ @apply text-xl leading-none;
132
+ }
133
+
134
+ .lesli-form-fieldset {
135
+ @apply mb-6 rounded-2xl border border-slate-200 bg-white p-6 shadow-sm;
136
+ }
137
+
138
+ .lesli-form-legend {
139
+ @apply -ml-1 mb-5 px-1 text-lg font-semibold text-slate-800;
140
+ }
141
+
142
+ .lesli-form-fieldset.is-info {
143
+ @apply border-sky-200 bg-sky-50/40;
144
+ }
145
+
146
+ .lesli-form-fieldset.is-success {
147
+ @apply border-emerald-200 bg-emerald-50/40;
148
+ }
149
+
150
+ .lesli-form-fieldset.is-warning {
151
+ @apply border-amber-200 bg-amber-50/50;
152
+ }
153
+
154
+ .lesli-form-fieldset.is-danger {
155
+ @apply border-rose-200 bg-rose-50/40;
156
+ }
157
+
158
+ @media (min-width: 768px) {
159
+ .lesli-form-field.is-horizontal {
160
+ @apply grid grid-cols-[minmax(8rem,1fr)_minmax(0,3fr)] items-start gap-5;
161
+ }
162
+
163
+ .lesli-form-field.is-horizontal > .lesli-form-label-wrapper {
164
+ @apply mb-0 pt-2.5 text-right;
165
+ }
166
+
167
+ .lesli-form-field.is-horizontal > .lesli-form-field-body {
168
+ @apply col-start-2;
169
+ }
170
+ }
171
+ }
@@ -31,57 +31,5 @@ Building a better future, one line of code at a time.
31
31
  */
32
32
 
33
33
 
34
- // ·
35
- .lesli-form-field {
36
- .field:not(.is-horizontal) {
37
- .field-label {
38
- text-align: left;
39
- }
40
- }
41
- }
42
-
43
-
44
- .lesli-form-fieldset {
45
- padding: 2.5rem 2rem;
46
- border-radius: 5px;
47
- //border: 1px solid #ccc;
48
- background-color: #fff;
49
- box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
50
-
51
- fieldset {
52
- padding: 1.2rem;
53
- border-radius: 5px;
54
- border: 1px solid #ccc;
55
- margin-bottom: 1rem;
56
- }
57
- }
58
-
59
-
60
- form fieldset.is-warning {
61
- border: 2px solid var(--bulma-warning);
62
- background-color: var(--bulma-warning-95);
63
- }
64
- form fieldset.is-warning h5 {
65
- color: var(--bulma-warning-bold);
66
- font-weight: 600;
67
- }
68
-
69
-
70
- form fieldset.is-info {
71
- border: 2px solid var(--bulma-info);
72
- background-color: var(--bulma-info-95);
73
- }
74
- form fieldset.is-info h5 {
75
- color: var(--bulma-info-bold);
76
- font-weight: 600;
77
- }
78
-
79
-
80
- form fieldset.is-danger {
81
- border: 2px solid var(--bulma-danger);
82
- background-color: var(--bulma-danger-95);
83
- }
84
- form fieldset.is-danger h5 {
85
- color: var(--bulma-danger-bold);
86
- font-weight: 600;
87
- }
34
+ // LesliView forms have migrated to Tailwind.
35
+ // See lib/lesli_view/forms/form.css.
@@ -2,17 +2,21 @@ module LesliView
2
2
  module Forms
3
3
  module Inputs
4
4
  def label(method, text = nil, options = {})
5
- super(method, text, options.merge(class: 'label'))
5
+ options = options.symbolize_keys
6
+ options[:class] = merge_css_classes("lesli-form-label", options[:class])
7
+ super(method, text, options)
6
8
  end
7
9
 
8
10
  def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
9
- value = @object.send(method)
11
+ options = options.symbolize_keys
12
+ options[:class] = merge_css_classes("lesli-form-checkbox", options[:class])
10
13
  super(method, options, checked_value, unchecked_value)
11
14
  end
12
15
 
13
16
  def text_field(method, options = {})
14
- value = @object.send(method) if @object
15
- super(method, options.merge(value: value, class: 'input'))
17
+ options = options.symbolize_keys
18
+ options[:class] = merge_css_classes("lesli-form-input", options[:class])
19
+ super(method, options)
16
20
  end
17
21
 
18
22
  def text_editor(method, options = {})
@@ -26,22 +30,30 @@ module LesliView
26
30
 
27
31
 
28
32
  def email_field(method, options = {})
29
- value = @object.send(method)
30
- super(method, options.merge(value: value, class: 'input'))
33
+ options = options.symbolize_keys
34
+ options[:class] = merge_css_classes("lesli-form-input", options[:class])
35
+ super(method, options)
31
36
  end
32
37
 
33
38
  def password_field(method, options = {})
34
- value = @object.send(method)
35
- super(method, options.merge(value: value, class: 'input'))
39
+ options = options.symbolize_keys
40
+ options[:class] = merge_css_classes("lesli-form-input", options[:class])
41
+ options[:value] = @object.public_send(method) if @object && !options.key?(:value)
42
+ super(method, options)
43
+ end
44
+
45
+ def select(method, choices = nil, options = {}, html_options = {}, &block)
46
+ html_options = html_options.symbolize_keys
47
+ html_options[:class] = merge_css_classes("lesli-form-select", html_options[:class])
48
+ super(method, choices, options, html_options, &block)
49
+ end
50
+
51
+ def submit(value = nil, options = {})
52
+ options = options.symbolize_keys
53
+ options[:class] = merge_css_classes("lesli-form-button is-primary", options[:class])
54
+ super(value, options)
36
55
  end
37
56
 
38
- def submit(value=nil, options = {})
39
- # Extract and merge classes properly
40
- default_classes = "button is-primary"
41
- custom_classes = options[:class] || ""
42
- merged_classes = "#{default_classes} #{custom_classes}".strip
43
- super(value, options.merge(class: merged_classes))
44
- end
45
57
  end
46
58
  end
47
59
  end
@@ -29,10 +29,8 @@ Building a better future, one line of code at a time.
29
29
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
30
  // ·
31
31
  %>
32
-
33
-
34
-
35
- <article class="lesli-items-activities" id="lesli-items-activities">
36
- <%= render(LesliView::Components::Timeline.new(activities:@activities, icons:@icons)) %>
32
+ <article
33
+ class="lesli-items-activities bg-white p-4 sm:p-8"
34
+ id="lesli-items-activities">
35
+ <%= render(LesliView::Components::Timeline.new(activities: @activities, icons: @icons)) %>
37
36
  </article>
38
-
@@ -1,9 +1,10 @@
1
- <div class="lesli-items-discussions-comments-comment is-flex mb-6">
2
- <div class="has-text-right">
3
- <strong>Luis Donis</strong> <br>
1
+ <li class="lesli-items-discussions-comments-comment flex flex-col gap-3 border-b border-slate-200 pb-6 last:border-b-0 last:pb-0 sm:flex-row sm:gap-4">
2
+ <div class="shrink-0 text-sm leading-5 text-slate-500 sm:w-40 sm:text-right">
3
+ <strong class="block font-semibold text-slate-800">Luis Donis</strong>
4
4
  <%= discussion['created_at_string'] || Date2.new.date_time %>
5
5
  </div>
6
- <div class="ml-4 is-fullwidth lexxy-content">
6
+
7
+ <div class="lexxy-content min-w-0 flex-1 break-words text-slate-700">
7
8
  <%== discussion.message %>
8
9
  </div>
9
- </div>
10
+ </li>
@@ -29,8 +29,8 @@ Building a better future, one line of code at a time.
29
29
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
30
  // ·
31
31
  %>
32
- <article class="lesli-items-discussions" id="lesli-items-discussions">
33
- <div class="lesli-items-discussions-form">
32
+ <article class="lesli-items-discussions bg-white p-4 sm:p-8" id="lesli-items-discussions">
33
+ <div class="lesli-items-discussions-form p-4">
34
34
  <% discussion_class = "#{@resource.class.name.deconstantize}::Items::Discussion".constantize %>
35
35
  <% scope_key = ActiveSupport::Inflector.underscore(discussion_class.name).tr("/", "_") %>
36
36
  <%= form_with(
@@ -45,13 +45,15 @@ Building a better future, one line of code at a time.
45
45
  <%= form.field_control_submit("Add comment") %>
46
46
  <% end %>
47
47
  </div>
48
- <hr />
49
- <div class="lesli-items-discussions-container">
50
- <ul id="<%="#{scope_key}-lesli-items-discussions-list"%>">
48
+ <hr class="my-6 border-0 border-t border-slate-200">
49
+
50
+ <div class="lesli-items-discussions-container p-4">
51
+ <ul
52
+ id="<%= "#{scope_key}-lesli-items-discussions-list" %>"
53
+ class="m-0 list-none space-y-6 p-0">
51
54
  <% @resource.discussions.order(created_at: :desc).each do |comment| %>
52
55
  <%= render(LesliView::Items::Discussion.new(comment)) %>
53
56
  <% end %>
54
57
  </ul>
55
58
  </div>
56
59
  </article>
57
-