neo_components 0.1.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 +7 -0
- data/app/assets/icons/academy.svg +3 -0
- data/app/assets/icons/adjustments-horizontal.svg +3 -0
- data/app/assets/icons/adjustments-vertical.svg +3 -0
- data/app/assets/icons/arrow-down-tray.svg +3 -0
- data/app/assets/icons/arrow-left.svg +3 -0
- data/app/assets/icons/arrow-long-down.svg +3 -0
- data/app/assets/icons/arrow-long-right.svg +3 -0
- data/app/assets/icons/arrow-long-up.svg +3 -0
- data/app/assets/icons/arrow-right.svg +3 -0
- data/app/assets/icons/arrow-up-tray.svg +3 -0
- data/app/assets/icons/arrow-uturn-left.svg +3 -0
- data/app/assets/icons/arrow-uturn-right.svg +3 -0
- data/app/assets/icons/assign-user.svg +13 -0
- data/app/assets/icons/at-symbol.svg +3 -0
- data/app/assets/icons/bars-4.svg +3 -0
- data/app/assets/icons/bell.svg +3 -0
- data/app/assets/icons/book.svg +3 -0
- data/app/assets/icons/bookmark.svg +3 -0
- data/app/assets/icons/building-office-2.svg +3 -0
- data/app/assets/icons/calendar.svg +3 -0
- data/app/assets/icons/celebration.svg +15 -0
- data/app/assets/icons/check-badge-solid.svg +3 -0
- data/app/assets/icons/check-circle-solid.svg +3 -0
- data/app/assets/icons/check-circle.svg +3 -0
- data/app/assets/icons/check-list.svg +12 -0
- data/app/assets/icons/check.svg +3 -0
- data/app/assets/icons/chevron-double-right.svg +3 -0
- data/app/assets/icons/chevron-down.svg +3 -0
- data/app/assets/icons/chevron-left.svg +3 -0
- data/app/assets/icons/chevron-right.svg +3 -0
- data/app/assets/icons/chevron-up.svg +3 -0
- data/app/assets/icons/circle-stack.svg +3 -0
- data/app/assets/icons/clipboard-document-check-solid.svg +4 -0
- data/app/assets/icons/clipboard-document-check.svg +3 -0
- data/app/assets/icons/clock.svg +3 -0
- data/app/assets/icons/complete.svg +3 -0
- data/app/assets/icons/course.svg +3 -0
- data/app/assets/icons/device-phone-mobile.svg +3 -0
- data/app/assets/icons/document-arrow-up.svg +4 -0
- data/app/assets/icons/document-text.svg +4 -0
- data/app/assets/icons/ellipsis-vertical.svg +3 -0
- data/app/assets/icons/exclaimation-circle-solid.svg +3 -0
- data/app/assets/icons/eye.svg +4 -0
- data/app/assets/icons/flag.svg +3 -0
- data/app/assets/icons/funnel.svg +3 -0
- data/app/assets/icons/green-circle.svg +3 -0
- data/app/assets/icons/green-tick.svg +3 -0
- data/app/assets/icons/grid.svg +6 -0
- data/app/assets/icons/home.svg +3 -0
- data/app/assets/icons/i-vector.svg +3 -0
- data/app/assets/icons/lessons.svg +11 -0
- data/app/assets/icons/magnifying-glass.svg +3 -0
- data/app/assets/icons/minus.svg +3 -0
- data/app/assets/icons/numbered-list.svg +3 -0
- data/app/assets/icons/pencil.svg +3 -0
- data/app/assets/icons/play.svg +3 -0
- data/app/assets/icons/plus.svg +3 -0
- data/app/assets/icons/power.svg +3 -0
- data/app/assets/icons/question-mark-circle.svg +3 -0
- data/app/assets/icons/quiz-score.svg +15 -0
- data/app/assets/icons/re-invite.svg +3 -0
- data/app/assets/icons/red-circle.svg +3 -0
- data/app/assets/icons/share.svg +3 -0
- data/app/assets/icons/smiley-five.svg +5 -0
- data/app/assets/icons/smiley-four.svg +5 -0
- data/app/assets/icons/smiley-one.svg +5 -0
- data/app/assets/icons/smiley-three.svg +5 -0
- data/app/assets/icons/smiley-two.svg +5 -0
- data/app/assets/icons/sparkle.svg +3 -0
- data/app/assets/icons/star-transparent.svg +3 -0
- data/app/assets/icons/stop.svg +4 -0
- data/app/assets/icons/support-placeholder.svg +4 -0
- data/app/assets/icons/tag.svg +4 -0
- data/app/assets/icons/timer.svg +5 -0
- data/app/assets/icons/transcript.svg +31 -0
- data/app/assets/icons/trash.svg +3 -0
- data/app/assets/icons/upload-info.svg +7 -0
- data/app/assets/icons/user-circle.svg +3 -0
- data/app/assets/icons/user-group.svg +3 -0
- data/app/assets/icons/user.svg +3 -0
- data/app/assets/icons/users.svg +3 -0
- data/app/assets/icons/winner.svg +35 -0
- data/app/assets/icons/x-circle-solid.svg +3 -0
- data/app/assets/icons/x-circle.svg +3 -0
- data/app/assets/icons/x-mark.svg +3 -0
- data/app/assets/stylesheets/breadcrumbs.tailwind.css +45 -0
- data/app/assets/stylesheets/buttons.tailwind.css +98 -0
- data/app/assets/stylesheets/course_progress.css +75 -0
- data/app/assets/stylesheets/custom.css +67 -0
- data/app/assets/stylesheets/date_picker.tailwind.css +7 -0
- data/app/assets/stylesheets/directives.tailwind.css +3 -0
- data/app/assets/stylesheets/dropdown.tailwind.css +11 -0
- data/app/assets/stylesheets/file_selector.tailwind.css +47 -0
- data/app/assets/stylesheets/icons.css.erb +244 -0
- data/app/assets/stylesheets/inputs.tailwind.css +53 -0
- data/app/assets/stylesheets/menu_component.tailwind.css +39 -0
- data/app/assets/stylesheets/mobile_inputs.tailwind.css +11 -0
- data/app/assets/stylesheets/modalbox.tailwind.css +35 -0
- data/app/assets/stylesheets/profile_icon.tailwind.css +15 -0
- data/app/assets/stylesheets/textarea.tailwind.css +43 -0
- data/app/assets/stylesheets/tooltip.css +88 -0
- data/app/assets/stylesheets/typography.tailwind.css +70 -0
- data/app/helpers/ui_helper.rb +31 -0
- data/app/helpers/view_component/accordion_component.rb +12 -0
- data/app/helpers/view_component/breadcrumbs_component.rb +30 -0
- data/app/helpers/view_component/button_component.rb +180 -0
- data/app/helpers/view_component/chip_component.rb +54 -0
- data/app/helpers/view_component/component_helper.rb +21 -0
- data/app/helpers/view_component/course_card_component.rb +9 -0
- data/app/helpers/view_component/course_carousal_component.rb +14 -0
- data/app/helpers/view_component/course_select_component.rb +32 -0
- data/app/helpers/view_component/doc_section_component.rb +10 -0
- data/app/helpers/view_component/icon_component.rb +24 -0
- data/app/helpers/view_component/input_component/date_picker_component.rb +127 -0
- data/app/helpers/view_component/input_component/dropdown_component.rb +99 -0
- data/app/helpers/view_component/input_component/file_selector_component.rb +123 -0
- data/app/helpers/view_component/input_component/input_checkbox_component.rb +54 -0
- data/app/helpers/view_component/input_component/input_mobile_component.rb +68 -0
- data/app/helpers/view_component/input_component/input_radio_component.rb +54 -0
- data/app/helpers/view_component/input_component/input_text_component.rb +137 -0
- data/app/helpers/view_component/input_component/textarea_component.rb +101 -0
- data/app/helpers/view_component/input_component.rb +290 -0
- data/app/helpers/view_component/input_textarea_component.rb +28 -0
- data/app/helpers/view_component/long_course_card_component.rb +10 -0
- data/app/helpers/view_component/member_list_component.rb +17 -0
- data/app/helpers/view_component/menu_component.rb +31 -0
- data/app/helpers/view_component/menu_component_helper.rb +22 -0
- data/app/helpers/view_component/menu_item.rb +12 -0
- data/app/helpers/view_component/modal_box_component.rb +29 -0
- data/app/helpers/view_component/modal_component.rb +12 -0
- data/app/helpers/view_component/notification_bar_component.rb +22 -0
- data/app/helpers/view_component/paginator_component.rb +9 -0
- data/app/helpers/view_component/profile_icon_component.rb +46 -0
- data/app/helpers/view_component/progress_component.rb +12 -0
- data/app/helpers/view_component/table_component.rb +22 -0
- data/app/helpers/view_component/typography_component.rb +83 -0
- data/app/javascript/neo_components/controllers/collapsible_controller.js +37 -0
- data/app/javascript/neo_components/controllers/date_picker_controller.js +17 -0
- data/app/javascript/neo_components/controllers/file_selector_controller.js +145 -0
- data/app/javascript/neo_components/controllers/input_mobile_controller.js +7 -0
- data/app/javascript/neo_components/controllers/menu_component_controller.js +26 -0
- data/app/javascript/neo_components/controllers/modal_loader_controller.js +13 -0
- data/app/javascript/neo_components/controllers/modals_controller.js +26 -0
- data/app/javascript/neo_components/controllers/notification_bar_controller.js +9 -0
- data/app/javascript/neo_components/controllers/pagination_controller.js +11 -0
- data/app/javascript/neo_components/controllers/tab_change_controller.js +23 -0
- data/app/javascript/neo_components/controllers/tabs_controller.js +29 -0
- data/app/javascript/neo_components/controllers/text_clamp_controller.js +29 -0
- data/app/views/shared/components/_progress_bar_short.html.erb +8 -0
- data/app/views/shared/components/_tooltip.html.erb +7 -0
- data/app/views/view_components/accordion_component/_accordion.html.erb +22 -0
- data/app/views/view_components/breadcrumbs_component/_breadcrumbs.html.erb +38 -0
- data/app/views/view_components/button_component/_button.html.erb +13 -0
- data/app/views/view_components/buttons/_danger.html.erb +30 -0
- data/app/views/view_components/buttons/_primary.html.erb +31 -0
- data/app/views/view_components/buttons/_secondary.html.erb +29 -0
- data/app/views/view_components/chip_component/_chip_component.html.erb +9 -0
- data/app/views/view_components/course_carousal/_course_card_component.html.erb +65 -0
- data/app/views/view_components/course_carousal/_course_carousal_body_component.html.erb +25 -0
- data/app/views/view_components/course_carousal/_course_carousal_component.html.erb +8 -0
- data/app/views/view_components/course_carousal/_long_course_card_component.html.erb +70 -0
- data/app/views/view_components/course_select/_course_select_component.html.erb +19 -0
- data/app/views/view_components/course_select/_list_component.html.erb +14 -0
- data/app/views/view_components/course_select/_list_item_component.html.erb +86 -0
- data/app/views/view_components/course_select/_load_more.html.erb +17 -0
- data/app/views/view_components/course_select/_search_component.html.erb +48 -0
- data/app/views/view_components/course_select/_sidebar_component.html.erb +41 -0
- data/app/views/view_components/doc_section/_doc_section_component.html.erb +6 -0
- data/app/views/view_components/inputs/_checkbox_field.html.erb +19 -0
- data/app/views/view_components/inputs/_date_select_component.html.erb +37 -0
- data/app/views/view_components/inputs/_dropdown_field.html.erb +22 -0
- data/app/views/view_components/inputs/_file_selector.html.erb +16 -0
- data/app/views/view_components/inputs/_input_checkbox_component.html.erb +7 -0
- data/app/views/view_components/inputs/_input_mobile_component.html.erb +16 -0
- data/app/views/view_components/inputs/_input_radio_component.html.erb +7 -0
- data/app/views/view_components/inputs/_input_text_component.html.erb +16 -0
- data/app/views/view_components/inputs/_mobile_field.html.erb +31 -0
- data/app/views/view_components/inputs/_radio_field.html.erb +25 -0
- data/app/views/view_components/inputs/_text_field.html.erb +52 -0
- data/app/views/view_components/inputs/_textarea.html.erb +26 -0
- data/app/views/view_components/inputs/date_picker_component/_date_picker.html.erb +16 -0
- data/app/views/view_components/inputs/date_picker_component/_input_box.html.erb +34 -0
- data/app/views/view_components/inputs/dropdown_component/_dropdown.html.erb +16 -0
- data/app/views/view_components/inputs/dropdown_component/_select_box.html.erb +10 -0
- data/app/views/view_components/inputs/file_selector_component/_file_selector_box.html.erb +76 -0
- data/app/views/view_components/inputs/input_checkbox/_checkbox.html.erb +20 -0
- data/app/views/view_components/inputs/input_mobile/_code.html.erb +13 -0
- data/app/views/view_components/inputs/input_mobile/_mobile_box.html.erb +4 -0
- data/app/views/view_components/inputs/input_mobile/_number.html.erb +13 -0
- data/app/views/view_components/inputs/input_radio/_radio_button.html.erb +14 -0
- data/app/views/view_components/inputs/input_text/_text_box.html.erb +33 -0
- data/app/views/view_components/inputs/textarea_component/_text_area_box.html.erb +16 -0
- data/app/views/view_components/inputs/textarea_component/_textarea.html.erb +16 -0
- data/app/views/view_components/member_list/_member_list.html.erb +4 -0
- data/app/views/view_components/member_list/_member_search.html.erb +15 -0
- data/app/views/view_components/member_list/_members.html.erb +65 -0
- data/app/views/view_components/menu_component/_menu_component.html.erb +16 -0
- data/app/views/view_components/menu_component/_menu_item_button.html.erb +17 -0
- data/app/views/view_components/menu_component/_menu_item_link.html.erb +5 -0
- data/app/views/view_components/menu_component_old/_menu_component.html.erb +17 -0
- data/app/views/view_components/menu_component_old/_menu_item_button.html.erb +7 -0
- data/app/views/view_components/menu_component_old/_menu_item_link.html.erb +5 -0
- data/app/views/view_components/modal_component/_modal_box_component.html.erb +28 -0
- data/app/views/view_components/modals/_modal_component.html.erb +25 -0
- data/app/views/view_components/notification_bar/_notification_bar.html.erb +17 -0
- data/app/views/view_components/paginator/_next_page.html.erb +7 -0
- data/app/views/view_components/paginator/_paginator_component.html.erb +6 -0
- data/app/views/view_components/paginator/_prev_page.html.erb +7 -0
- data/app/views/view_components/profile_icon_component/_profile_icon.html.erb +3 -0
- data/app/views/view_components/progress_component/_progressbar.html.erb +5 -0
- data/app/views/view_components/typography/_h1_component.html.erb +1 -0
- data/app/views/view_components/typography/_h2_component.html.erb +1 -0
- data/app/views/view_components/typography/_h3_component.html.erb +1 -0
- data/app/views/view_components/typography/_heading_component.html.erb +3 -0
- data/app/views/view_components/typography/_link_component.html.erb +1 -0
- data/app/views/view_components/typography/_linked_text_component.html.erb +3 -0
- data/app/views/view_components/typography/_text_component.html.erb +1 -0
- data/config/importmap.rb +5 -0
- data/lib/neo_components/engine.rb +38 -0
- data/lib/neo_components/version.rb +5 -0
- data/lib/neo_components.rb +4 -0
- metadata +327 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
class InputCheckboxComponent
|
|
6
|
+
include ViewComponent::ComponentHelper
|
|
7
|
+
|
|
8
|
+
attr_accessor :form, :name, :label, :value, :disabled, :error, :label_position, :html_options
|
|
9
|
+
|
|
10
|
+
def initialize(form:, name:, label:, value:, disabled:, error:, label_position:, html_options:)
|
|
11
|
+
self.form = form
|
|
12
|
+
self.name = name
|
|
13
|
+
self.label = label
|
|
14
|
+
self.label_position = label_position
|
|
15
|
+
self.value = value
|
|
16
|
+
self.html_options = html_options
|
|
17
|
+
self.disabled = disabled
|
|
18
|
+
self.html_options[:disabled] = disabled
|
|
19
|
+
self.html_options[:class] = 'hidden peer'
|
|
20
|
+
self.error = resolve_error(form, name, error)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def label_style
|
|
24
|
+
if disabled
|
|
25
|
+
'text-disabled-color'
|
|
26
|
+
elsif error
|
|
27
|
+
'text-danger-dark'
|
|
28
|
+
else
|
|
29
|
+
'text-letter-color group-has-[input:checked]:text-primary group-hover:text-primary-light'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def box_style
|
|
34
|
+
if disabled
|
|
35
|
+
'border-disabled-color'
|
|
36
|
+
elsif error
|
|
37
|
+
'border-danger-dark'
|
|
38
|
+
else
|
|
39
|
+
'border-slate-grey-50 group-hover:border-primary-light group-has-[input:checked]:border-primary'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def check_style
|
|
44
|
+
if disabled
|
|
45
|
+
'hidden'
|
|
46
|
+
elsif error
|
|
47
|
+
'hidden group-has-[input:checked]:flex group-has-[input:checked]:text-danger-dark'
|
|
48
|
+
else
|
|
49
|
+
'hidden group-has-[input:checked]:flex group-has-[input:checked]:text-primary'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
class InputMobileComponent < InputTextComponent
|
|
6
|
+
CODE_WIDTH = {
|
|
7
|
+
md: 'w-16',
|
|
8
|
+
lg: 'w-20'
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
CODE_SELECT_WIDTH = {
|
|
12
|
+
md: 'w-20',
|
|
13
|
+
lg: 'w-24'
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
CODE_TEXT = {
|
|
17
|
+
md: 'mobile-code-md',
|
|
18
|
+
lg: 'mobile-code-lg'
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
attr_accessor :form, :code_name, :name, :label, :type, :code_value, :value, :subtext, :error,
|
|
22
|
+
:icon_name, :icon_position, :disabled, :size, :html_options
|
|
23
|
+
|
|
24
|
+
def initialize(form:, name:, label:, type:, placeholder:, code_value:, value:, subtext:, error:,
|
|
25
|
+
icon_name:, icon_position:, disabled:, size:, html_options:)
|
|
26
|
+
super(form:, name:, label:, type:, placeholder:, value:, subtext:, error:, icon_name:, icon_position:,
|
|
27
|
+
disabled:, size:, html_options:)
|
|
28
|
+
self.code_value = code_value
|
|
29
|
+
self.code_name = name.present? ? "#{name}_code" : 'code'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def code_selectable?
|
|
33
|
+
code_value.blank?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def error_style
|
|
37
|
+
base = ['text-danger border-danger-dark',
|
|
38
|
+
'group-focus-within:ring-danger-dark group-focus-within:border-danger-dark']
|
|
39
|
+
base << 'group-focus-within:ring-1' unless code_selectable?
|
|
40
|
+
base.join(' ')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def normal_style
|
|
44
|
+
base = ['border-slate-grey-50 group-focus-within:border-primary']
|
|
45
|
+
base << 'group-focus-within:ring-primary' if code_selectable?
|
|
46
|
+
base.join(' ')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def code_wrapper_style
|
|
50
|
+
base = ['mobile-code-base']
|
|
51
|
+
color_style = if disabled
|
|
52
|
+
'border-disabled-color'
|
|
53
|
+
elsif error.present?
|
|
54
|
+
error_style
|
|
55
|
+
elsif code_selectable?
|
|
56
|
+
'border-slate-grey-50 group-focus:ring-primary group-focus:border-primary'
|
|
57
|
+
else
|
|
58
|
+
'border-slate-grey-50 group-focus-within:border-primary'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
size_style = INPUT_WRAPPER_STYLES[size.to_sym]
|
|
62
|
+
code_width = code_selectable? ? CODE_SELECT_WIDTH[size.to_sym] : CODE_WIDTH[size.to_sym]
|
|
63
|
+
code_text = CODE_TEXT[size.to_sym]
|
|
64
|
+
[class_list(base, size_style, color_style), code_width, code_text].join(' ')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
class InputRadioComponent
|
|
6
|
+
include ViewComponent::ComponentHelper
|
|
7
|
+
|
|
8
|
+
attr_accessor :form, :name, :label, :value, :disabled, :error, :label_position, :html_options
|
|
9
|
+
|
|
10
|
+
def initialize(form:, name:, label:, value:, disabled:, error:, label_position:, html_options:)
|
|
11
|
+
self.form = form
|
|
12
|
+
self.name = name
|
|
13
|
+
self.label = label
|
|
14
|
+
self.label_position = label_position
|
|
15
|
+
self.value = value
|
|
16
|
+
self.html_options = html_options
|
|
17
|
+
self.disabled = disabled
|
|
18
|
+
self.html_options[:disabled] = disabled
|
|
19
|
+
self.html_options[:class] = 'hidden'
|
|
20
|
+
self.error = resolve_error(form, name, error)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def label_style
|
|
24
|
+
if disabled
|
|
25
|
+
'text-disabled-color'
|
|
26
|
+
elsif error
|
|
27
|
+
'text-danger-dark'
|
|
28
|
+
else
|
|
29
|
+
'text-letter-color group-has-[input:checked]:text-primary group-hover:text-primary-light'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def radio_circle_style
|
|
34
|
+
if disabled
|
|
35
|
+
'border-disabled-color'
|
|
36
|
+
elsif error
|
|
37
|
+
'border-danger-dark'
|
|
38
|
+
else
|
|
39
|
+
'border-slate-grey-50 group-hover:border-primary-light group-has-[input:checked]:border-primary'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def radio_dot_style
|
|
44
|
+
if disabled
|
|
45
|
+
'bg-white'
|
|
46
|
+
elsif error
|
|
47
|
+
'group-has-[input:checked]:bg-danger-dark'
|
|
48
|
+
else
|
|
49
|
+
'group-has-[input:checked]:bg-primary'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
class InputTextComponent
|
|
6
|
+
include ViewComponent::ComponentHelper
|
|
7
|
+
|
|
8
|
+
INPUT_SIZE_STYLE = {
|
|
9
|
+
md: 'input-text-md',
|
|
10
|
+
lg: 'input-text-lg'
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
ICON_SIZE = {
|
|
14
|
+
md: 'input-text-icon-md',
|
|
15
|
+
lg: 'input-text-icon-lg'
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
INPUT_WRAPPER_STYLES = {
|
|
19
|
+
md: 'input-text-div-base-md',
|
|
20
|
+
lg: 'input-text-div-base-lg'
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
LABEL_STYLES = {
|
|
24
|
+
md: 'input-text-label-md',
|
|
25
|
+
lg: 'input-text-label-lg'
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
SUBTEXT_SIZE = {
|
|
29
|
+
md: 'input-text-subtext-md',
|
|
30
|
+
lg: 'input-text-subtext-lg'
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
attr_accessor :form, :name, :label, :type, :value, :subtext, :error, :icon_name, :icon_position, :disabled, :size,
|
|
34
|
+
:html_options
|
|
35
|
+
|
|
36
|
+
def initialize(form:, name:, label:, type:, placeholder:, value:, subtext:, error:,
|
|
37
|
+
icon_name:, icon_position:, disabled:, size:, html_options:)
|
|
38
|
+
error_message = resolve_error(form, name, error)
|
|
39
|
+
|
|
40
|
+
self.form = form
|
|
41
|
+
self.name = name
|
|
42
|
+
self.label = label
|
|
43
|
+
self.type = type
|
|
44
|
+
self.value = value
|
|
45
|
+
self.subtext = error_message.presence || subtext # Prioritise error over subtext
|
|
46
|
+
self.error = error_message
|
|
47
|
+
self.icon_name = icon_name
|
|
48
|
+
self.icon_position = icon_position
|
|
49
|
+
self.disabled = disabled
|
|
50
|
+
self.size = size
|
|
51
|
+
self.html_options = html_options
|
|
52
|
+
self.html_options[:placeholder] = placeholder
|
|
53
|
+
self.html_options[:class] = input_style
|
|
54
|
+
self.html_options[:disabled] = disabled if disabled
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def input_style
|
|
58
|
+
base = ['input-text-base']
|
|
59
|
+
color_style = if disabled
|
|
60
|
+
'text-disabled-color'
|
|
61
|
+
elsif error.present?
|
|
62
|
+
'text-danger focus:text-danger-dark'
|
|
63
|
+
else
|
|
64
|
+
'text-disabled-color focus:text-letter-color'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
size_style = INPUT_SIZE_STYLE[size.to_sym]
|
|
68
|
+
class_list(base, size_style, color_style)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def placeholder
|
|
72
|
+
html_options[:placeholder]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def placeholder=(value)
|
|
76
|
+
html_options[:placeholder] = value
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def input_wrapper_style
|
|
80
|
+
base = ['input-text-div-base group']
|
|
81
|
+
color_style = if disabled
|
|
82
|
+
'border-disabled-color'
|
|
83
|
+
elsif error.present?
|
|
84
|
+
'border-danger focus-within:border-danger-dark ring-danger-dark'
|
|
85
|
+
else
|
|
86
|
+
'border-slate-grey-50 focus-within:border-primary ring-primary'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
size_style = INPUT_WRAPPER_STYLES[size.to_sym]
|
|
90
|
+
class_list(base, size_style, color_style)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def label_style
|
|
94
|
+
base = []
|
|
95
|
+
color_style = if disabled
|
|
96
|
+
'text-disabled-color'
|
|
97
|
+
elsif error.present?
|
|
98
|
+
'text-danger-dark'
|
|
99
|
+
else
|
|
100
|
+
'text-letter-color-light group-focus-within:text-primary'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
size_style = LABEL_STYLES[size.to_sym]
|
|
104
|
+
class_list(base, size_style, color_style)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def icon_style
|
|
108
|
+
base = ['input-text-icon-base']
|
|
109
|
+
color_style = if disabled
|
|
110
|
+
'text-disabled-color'
|
|
111
|
+
elsif error.present?
|
|
112
|
+
'text-danger-dark'
|
|
113
|
+
else
|
|
114
|
+
'text-disabled-color group-focus-within:text-letter-color'
|
|
115
|
+
end
|
|
116
|
+
class_list(base, '', color_style)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def icon_size
|
|
120
|
+
ICON_SIZE[size.to_sym]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def subtext_style
|
|
124
|
+
base = []
|
|
125
|
+
color_style = if disabled
|
|
126
|
+
'text-disabled-color'
|
|
127
|
+
elsif error.present?
|
|
128
|
+
'text-danger-dark'
|
|
129
|
+
else
|
|
130
|
+
'text-letter-color-light'
|
|
131
|
+
end
|
|
132
|
+
size_style = SUBTEXT_SIZE[size.to_sym]
|
|
133
|
+
class_list(base, size_style, color_style)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
class TextareaComponent
|
|
6
|
+
include ViewComponent::ComponentHelper
|
|
7
|
+
|
|
8
|
+
TEXTAREA_SIZES = %w[md lg].freeze
|
|
9
|
+
|
|
10
|
+
TEXTAREA_SIZE_STYLE = {
|
|
11
|
+
md: 'textarea-component-md main-text-md-normal',
|
|
12
|
+
lg: 'textarea-component-lg main-text-lg-medium'
|
|
13
|
+
}.freeze
|
|
14
|
+
|
|
15
|
+
LABEL_STYLES = {
|
|
16
|
+
md: 'general-text-sm-normal',
|
|
17
|
+
lg: 'general-text-md-normal'
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
SUPPORT_TEXT_STYLES = {
|
|
21
|
+
md: 'general-text-sm-normal px-3',
|
|
22
|
+
lg: 'general-text-md-normal px-3 md:px-4'
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
attr_accessor :form, :name, :label, :placeholder, :value,
|
|
26
|
+
:rows, :size, :support_text, :error, :disabled, :html_options
|
|
27
|
+
|
|
28
|
+
def initialize(form:, name:, label:, placeholder:, value:, rows:, size:, support_text:,
|
|
29
|
+
error:, disabled:, html_options:)
|
|
30
|
+
raise "Incorrect textarea size: #{size}" unless TEXTAREA_SIZES.include?(size)
|
|
31
|
+
|
|
32
|
+
error_message = resolve_error(form, name, error)
|
|
33
|
+
|
|
34
|
+
self.form = form
|
|
35
|
+
self.name = name
|
|
36
|
+
self.label = label
|
|
37
|
+
self.placeholder = placeholder
|
|
38
|
+
self.value = value
|
|
39
|
+
self.rows = rows
|
|
40
|
+
self.size = size
|
|
41
|
+
self.support_text = (error_message.presence || support_text)
|
|
42
|
+
self.error = error_message
|
|
43
|
+
self.disabled = disabled
|
|
44
|
+
self.html_options = html_options
|
|
45
|
+
|
|
46
|
+
self.html_options[:placeholder] = placeholder
|
|
47
|
+
self.html_options[:rows] ||= rows
|
|
48
|
+
self.html_options[:disabled] = true if disabled
|
|
49
|
+
self.html_options[:class] = textarea_style
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def textarea_style
|
|
53
|
+
base = ['textarea-component-base field-sizing-content']
|
|
54
|
+
size_style = TEXTAREA_SIZE_STYLE[size.to_sym]
|
|
55
|
+
|
|
56
|
+
color_style =
|
|
57
|
+
if disabled
|
|
58
|
+
'textarea-disabled-state'
|
|
59
|
+
elsif error.present?
|
|
60
|
+
'textarea-error-state'
|
|
61
|
+
else
|
|
62
|
+
'textarea-active-state'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class_list(base, size_style, color_style)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def label_style
|
|
69
|
+
base = ['textarea-label']
|
|
70
|
+
size_style = LABEL_STYLES[size.to_sym]
|
|
71
|
+
|
|
72
|
+
color_style =
|
|
73
|
+
if disabled
|
|
74
|
+
'text-disabled-color'
|
|
75
|
+
elsif error.present?
|
|
76
|
+
'text-danger-dark'
|
|
77
|
+
else
|
|
78
|
+
'text-letter-color-light group-focus-within:text-primary'
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class_list(base, size_style, color_style)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def support_text_style
|
|
85
|
+
base = ['textarea-support-text']
|
|
86
|
+
size_style = SUPPORT_TEXT_STYLES[size.to_sym]
|
|
87
|
+
|
|
88
|
+
color_style =
|
|
89
|
+
if disabled
|
|
90
|
+
'text-disabled-color'
|
|
91
|
+
elsif error.present?
|
|
92
|
+
'text-danger-dark'
|
|
93
|
+
else
|
|
94
|
+
'text-slate-grey-50'
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class_list(base, size_style, color_style)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ViewComponent
|
|
4
|
+
module InputComponent
|
|
5
|
+
def input_field(form: nil, field_name: nil, label: nil,
|
|
6
|
+
placeholder: nil, width: 'w-56', height: nil, left_icon: nil, right_icon: nil, type: 'text',
|
|
7
|
+
options: [], value: nil, rows: '5', option: nil, html_options: {})
|
|
8
|
+
partial_path = 'view_components/inputs/text_field' unless lookup_context.exists?(partial_path, [], true)
|
|
9
|
+
|
|
10
|
+
html_options[:data] ||= {}
|
|
11
|
+
|
|
12
|
+
render partial: partial_path, locals: {
|
|
13
|
+
form:,
|
|
14
|
+
field_name:,
|
|
15
|
+
label:,
|
|
16
|
+
placeholder:,
|
|
17
|
+
width:,
|
|
18
|
+
height:,
|
|
19
|
+
left_icon:,
|
|
20
|
+
right_icon:,
|
|
21
|
+
type:,
|
|
22
|
+
options:,
|
|
23
|
+
value:,
|
|
24
|
+
rows:,
|
|
25
|
+
option:,
|
|
26
|
+
html_options:
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def input_radio(form: nil, field_name: nil, label: nil,
|
|
31
|
+
placeholder: 'Enter text', width: 'w-56', height: nil,
|
|
32
|
+
value: nil, option: nil, html_options: {})
|
|
33
|
+
render partial: 'view_components/inputs/radio_field', locals: {
|
|
34
|
+
form:,
|
|
35
|
+
field_name:,
|
|
36
|
+
label:,
|
|
37
|
+
placeholder:,
|
|
38
|
+
width:,
|
|
39
|
+
height:,
|
|
40
|
+
value:,
|
|
41
|
+
option:,
|
|
42
|
+
html_options:
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def input_dropdown(form: nil, field_name: nil, label: nil,
|
|
47
|
+
width: 'w-56', height: nil, placeholder: nil,
|
|
48
|
+
options: [], value: nil, html_options: {})
|
|
49
|
+
render partial: 'view_components/inputs/dropdown_field', locals: {
|
|
50
|
+
form:,
|
|
51
|
+
field_name:,
|
|
52
|
+
label:,
|
|
53
|
+
width:,
|
|
54
|
+
height:,
|
|
55
|
+
placeholder:,
|
|
56
|
+
options:,
|
|
57
|
+
value:,
|
|
58
|
+
html_options:
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def input_checkbox(form: nil, field_name: nil, label: nil, width: 'w-56',
|
|
63
|
+
value: nil, allow_multiple: false)
|
|
64
|
+
render partial: 'view_components/inputs/checkbox_field', locals: {
|
|
65
|
+
form:,
|
|
66
|
+
field_name:,
|
|
67
|
+
label:,
|
|
68
|
+
width:,
|
|
69
|
+
value:,
|
|
70
|
+
allow_multiple:
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def input_mobile(form:, field_name:, placeholder: 'Enter 10-digit mobile number',
|
|
75
|
+
value: nil, label: nil, flag: nil, html_options: {})
|
|
76
|
+
value ||= form.object.public_send(field_name) if form.object.respond_to?(field_name)
|
|
77
|
+
|
|
78
|
+
render partial: 'view_components/inputs/mobile_field', locals: {
|
|
79
|
+
form:,
|
|
80
|
+
field_name:,
|
|
81
|
+
placeholder:,
|
|
82
|
+
value:,
|
|
83
|
+
label:,
|
|
84
|
+
flag:,
|
|
85
|
+
html_options:
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def input_otp(form:, field_prefix: 'otp', count: 4, input_options: {}, wrapper_options: {})
|
|
90
|
+
content_tag(:div, class: 'flex justify-between gap-6 w-full', **(wrapper_options || {}).except(:data)) do
|
|
91
|
+
safe_join(
|
|
92
|
+
count.times.map do |i|
|
|
93
|
+
field_name = "#{field_prefix}_#{number_to_human(i + 1)}"
|
|
94
|
+
|
|
95
|
+
input_field(
|
|
96
|
+
form:,
|
|
97
|
+
field_name:,
|
|
98
|
+
type: 'text',
|
|
99
|
+
width: 'min-w-16',
|
|
100
|
+
html_options: {
|
|
101
|
+
class: 'input-text-otp',
|
|
102
|
+
maxlength: 1,
|
|
103
|
+
inputmode: 'numeric',
|
|
104
|
+
pattern: '[0-9]*'
|
|
105
|
+
}.merge(input_options)
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# form component date_select_component
|
|
113
|
+
# @param min minimum date
|
|
114
|
+
# @param maximum date
|
|
115
|
+
def date_select_component(form:, field_name:, min: nil, max: nil, placeholder: 'YYYY-MM-DD')
|
|
116
|
+
render partial: 'view_components/inputs/date_select_component',
|
|
117
|
+
locals: { form:, field_name:, min:, max:, placeholder: }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def input_text_component(
|
|
121
|
+
form: nil,
|
|
122
|
+
name: nil,
|
|
123
|
+
label: nil,
|
|
124
|
+
type: 'text',
|
|
125
|
+
placeholder: 'Placeholder',
|
|
126
|
+
value: '',
|
|
127
|
+
subtext: nil,
|
|
128
|
+
error: nil,
|
|
129
|
+
icon_name: nil,
|
|
130
|
+
icon_position: 'right',
|
|
131
|
+
disabled: false,
|
|
132
|
+
size: 'md',
|
|
133
|
+
html_options: {}
|
|
134
|
+
)
|
|
135
|
+
input = InputTextComponent.new(
|
|
136
|
+
form:, name:, label:, type:, placeholder:, value:, subtext:, error:, icon_name:, icon_position:, disabled:,
|
|
137
|
+
size:, html_options:
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
render partial: 'view_components/inputs/input_text_component',
|
|
141
|
+
locals: { input: }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def input_radio_component(form: nil, name: nil, label: nil, value: nil, disabled: false, error: nil,
|
|
145
|
+
label_position: 'right',
|
|
146
|
+
html_options: {})
|
|
147
|
+
input = InputRadioComponent.new(
|
|
148
|
+
form:, name:, label:, value:, disabled:, error:, label_position:, html_options:
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
render partial: 'view_components/inputs/input_radio_component',
|
|
152
|
+
locals: { input: }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def input_checkbox_component(form: nil, name: nil, label: nil, value: nil, disabled: false, error: nil,
|
|
156
|
+
label_position: 'right',
|
|
157
|
+
html_options: {})
|
|
158
|
+
input = InputCheckboxComponent.new(
|
|
159
|
+
form:, name:, label:, value:, disabled:, error:, label_position:, html_options:
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
render partial: 'view_components/inputs/input_checkbox_component',
|
|
163
|
+
locals: { input: }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def file_selector_component(type:, form: nil, name: nil, label: nil, support_text: nil,
|
|
167
|
+
support_text_two: nil, error: nil,
|
|
168
|
+
disabled: false, html_options: {})
|
|
169
|
+
file_selector = FileSelectorComponent.new(
|
|
170
|
+
form:, name:, label:, support_text:, support_text_two:, error:, disabled:, html_options:, type:
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
render partial: 'view_components/inputs/file_selector', locals: { file_selector: }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def input_mobile_component(
|
|
177
|
+
form: nil,
|
|
178
|
+
name: nil,
|
|
179
|
+
label: nil,
|
|
180
|
+
placeholder: 'Enter your mobile number',
|
|
181
|
+
country_code: '',
|
|
182
|
+
value: '',
|
|
183
|
+
subtext: nil,
|
|
184
|
+
error: nil,
|
|
185
|
+
icon_name: nil,
|
|
186
|
+
icon_position: 'right',
|
|
187
|
+
disabled: false,
|
|
188
|
+
size: 'md',
|
|
189
|
+
html_options: {}
|
|
190
|
+
)
|
|
191
|
+
input = InputMobileComponent.new(
|
|
192
|
+
form:, name:, label:, type: 'number', placeholder:, code_value: country_code, value:, subtext:, error:,
|
|
193
|
+
icon_name:, icon_position:, disabled:, size:, html_options:
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
render partial: 'view_components/inputs/input_mobile_component',
|
|
197
|
+
locals: { input: }
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def textarea_component(
|
|
201
|
+
name:,
|
|
202
|
+
placeholder:,
|
|
203
|
+
form: nil,
|
|
204
|
+
label: nil,
|
|
205
|
+
value: nil,
|
|
206
|
+
rows: 1,
|
|
207
|
+
size: 'md',
|
|
208
|
+
support_text: nil,
|
|
209
|
+
error: nil,
|
|
210
|
+
disabled: false,
|
|
211
|
+
html_options: {}
|
|
212
|
+
)
|
|
213
|
+
textarea = TextareaComponent.new(
|
|
214
|
+
form:,
|
|
215
|
+
name:,
|
|
216
|
+
label:,
|
|
217
|
+
placeholder:,
|
|
218
|
+
value:,
|
|
219
|
+
rows:,
|
|
220
|
+
size:,
|
|
221
|
+
support_text:,
|
|
222
|
+
error:,
|
|
223
|
+
disabled:,
|
|
224
|
+
html_options:
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
render partial: 'view_components/inputs/textarea_component/textarea', locals: { textarea: }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def dropdown_component(
|
|
231
|
+
form: nil,
|
|
232
|
+
name: nil,
|
|
233
|
+
label: nil,
|
|
234
|
+
options: [],
|
|
235
|
+
value: nil,
|
|
236
|
+
size: 'md',
|
|
237
|
+
support_text: nil,
|
|
238
|
+
error: nil,
|
|
239
|
+
disabled: false,
|
|
240
|
+
html_options: {},
|
|
241
|
+
prompt: nil
|
|
242
|
+
)
|
|
243
|
+
dropdown = DropdownComponent.new(
|
|
244
|
+
form:,
|
|
245
|
+
name:,
|
|
246
|
+
label:,
|
|
247
|
+
options:,
|
|
248
|
+
value:,
|
|
249
|
+
size:,
|
|
250
|
+
support_text:,
|
|
251
|
+
error:,
|
|
252
|
+
disabled:,
|
|
253
|
+
html_options:,
|
|
254
|
+
prompt:
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
render partial: 'view_components/inputs/dropdown_component/dropdown',
|
|
258
|
+
locals: { dropdown: }
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def date_picker_component(
|
|
262
|
+
form: nil,
|
|
263
|
+
name: nil,
|
|
264
|
+
label: nil,
|
|
265
|
+
value: nil,
|
|
266
|
+
placeholder: nil,
|
|
267
|
+
size: 'md',
|
|
268
|
+
support_text: nil,
|
|
269
|
+
error: nil,
|
|
270
|
+
disabled: false,
|
|
271
|
+
html_options: {}
|
|
272
|
+
)
|
|
273
|
+
date_picker = DatePickerComponent.new(
|
|
274
|
+
form:,
|
|
275
|
+
name:,
|
|
276
|
+
label:,
|
|
277
|
+
value:,
|
|
278
|
+
placeholder:,
|
|
279
|
+
size:,
|
|
280
|
+
support_text:,
|
|
281
|
+
error:,
|
|
282
|
+
disabled:,
|
|
283
|
+
html_options:
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
render partial: 'view_components/inputs/date_picker_component/date_picker',
|
|
287
|
+
locals: { date_picker: }
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|