rails-active-ui 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/Rakefile +6 -0
- data/app/assets/stylesheets.css +73555 -0
- data/app/components/accordion_component.rb +34 -0
- data/app/components/ad_component.rb +28 -0
- data/app/components/api_component.rb +24 -0
- data/app/components/breadcrumb_component.rb +26 -0
- data/app/components/button_component.rb +49 -0
- data/app/components/calendar_component.rb +34 -0
- data/app/components/card_component.rb +56 -0
- data/app/components/checkbox_component.rb +41 -0
- data/app/components/column_component.rb +62 -0
- data/app/components/comment_component.rb +45 -0
- data/app/components/concerns/alignable.rb +21 -0
- data/app/components/concerns/attachable.rb +16 -0
- data/app/components/concerns/orientable.rb +21 -0
- data/app/components/concerns/positionable.rb +21 -0
- data/app/components/concerns/sizeable.rb +18 -0
- data/app/components/container_component.rb +23 -0
- data/app/components/dimmer_component.rb +30 -0
- data/app/components/divider_component.rb +30 -0
- data/app/components/dropdown_component.rb +63 -0
- data/app/components/embed_component.rb +32 -0
- data/app/components/emoji_component.rb +15 -0
- data/app/components/feed_component.rb +22 -0
- data/app/components/flag_component.rb +15 -0
- data/app/components/flyout_component.rb +41 -0
- data/app/components/form_component.rb +39 -0
- data/app/components/grid_component.rb +85 -0
- data/app/components/h_stack_component.rb +67 -0
- data/app/components/header_component.rb +60 -0
- data/app/components/icon_component.rb +41 -0
- data/app/components/image_component.rb +46 -0
- data/app/components/input_component.rb +52 -0
- data/app/components/item_component.rb +39 -0
- data/app/components/item_group_component.rb +30 -0
- data/app/components/label_component.rb +49 -0
- data/app/components/link_component.rb +23 -0
- data/app/components/list_component.rb +39 -0
- data/app/components/loader_component.rb +33 -0
- data/app/components/menu_component.rb +64 -0
- data/app/components/menu_item_component.rb +52 -0
- data/app/components/message_component.rb +54 -0
- data/app/components/modal_component.rb +50 -0
- data/app/components/nag_component.rb +25 -0
- data/app/components/overlay_component.rb +16 -0
- data/app/components/placeholder_component.rb +39 -0
- data/app/components/popup_component.rb +31 -0
- data/app/components/progress_component.rb +48 -0
- data/app/components/pusher_component.rb +18 -0
- data/app/components/rail_component.rb +31 -0
- data/app/components/rating_component.rb +41 -0
- data/app/components/reset_component.rb +12 -0
- data/app/components/reveal_component.rb +39 -0
- data/app/components/row_component.rb +39 -0
- data/app/components/search_component.rb +44 -0
- data/app/components/segment_component.rb +57 -0
- data/app/components/segment_group_component.rb +36 -0
- data/app/components/shape_component.rb +25 -0
- data/app/components/sidebar_component.rb +33 -0
- data/app/components/site_component.rb +12 -0
- data/app/components/slider_component.rb +46 -0
- data/app/components/state_component.rb +25 -0
- data/app/components/statistic_component.rb +43 -0
- data/app/components/step_component.rb +56 -0
- data/app/components/step_group_component.rb +38 -0
- data/app/components/sticky_component.rb +22 -0
- data/app/components/sub_header_component.rb +15 -0
- data/app/components/sub_menu_component.rb +24 -0
- data/app/components/tab_component.rb +24 -0
- data/app/components/table_cell_component.rb +60 -0
- data/app/components/table_component.rb +160 -0
- data/app/components/table_row_component.rb +43 -0
- data/app/components/text_component.rb +73 -0
- data/app/components/toast_component.rb +36 -0
- data/app/components/transition_component.rb +32 -0
- data/app/components/v_stack_component.rb +31 -0
- data/app/components/visibility_component.rb +22 -0
- data/app/helpers/component_helper.rb +109 -0
- data/app/helpers/fui_helper.rb +53 -0
- data/app/javascript/accordion.js +547 -0
- data/app/javascript/accordion.min.js +11 -0
- data/app/javascript/api.js +1112 -0
- data/app/javascript/api.min.js +11 -0
- data/app/javascript/calendar.js +1960 -0
- data/app/javascript/calendar.min.js +11 -0
- data/app/javascript/checkbox.js +819 -0
- data/app/javascript/checkbox.min.js +11 -0
- data/app/javascript/dimmer.js +686 -0
- data/app/javascript/dimmer.min.js +11 -0
- data/app/javascript/dropdown.js +4019 -0
- data/app/javascript/dropdown.min.js +11 -0
- data/app/javascript/embed.js +646 -0
- data/app/javascript/embed.min.js +11 -0
- data/app/javascript/flyout.js +1405 -0
- data/app/javascript/flyout.min.js +11 -0
- data/app/javascript/form.js +2070 -0
- data/app/javascript/form.min.js +11 -0
- data/app/javascript/jquery.js +10716 -0
- data/app/javascript/jquery.min.js +2 -0
- data/app/javascript/modal.js +1507 -0
- data/app/javascript/modal.min.js +11 -0
- data/app/javascript/nag.js +522 -0
- data/app/javascript/nag.min.js +11 -0
- data/app/javascript/popup.js +1457 -0
- data/app/javascript/popup.min.js +11 -0
- data/app/javascript/progress.js +922 -0
- data/app/javascript/progress.min.js +11 -0
- data/app/javascript/rating.js +496 -0
- data/app/javascript/rating.min.js +11 -0
- data/app/javascript/search.js +1519 -0
- data/app/javascript/search.min.js +11 -0
- data/app/javascript/shape.js +721 -0
- data/app/javascript/shape.min.js +11 -0
- data/app/javascript/sidebar.js +952 -0
- data/app/javascript/sidebar.min.js +11 -0
- data/app/javascript/site.js +415 -0
- data/app/javascript/site.min.js +11 -0
- data/app/javascript/slider.js +1449 -0
- data/app/javascript/slider.min.js +11 -0
- data/app/javascript/state.js +653 -0
- data/app/javascript/state.min.js +11 -0
- data/app/javascript/sticky.js +852 -0
- data/app/javascript/sticky.min.js +11 -0
- data/app/javascript/tab.js +867 -0
- data/app/javascript/tab.min.js +11 -0
- data/app/javascript/toast.js +916 -0
- data/app/javascript/toast.min.js +11 -0
- data/app/javascript/transition.js +955 -0
- data/app/javascript/transition.min.js +11 -0
- data/app/javascript/ui/controllers/fui_accordion_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_api_controller.js +80 -0
- data/app/javascript/ui/controllers/fui_calendar_controller.js +66 -0
- data/app/javascript/ui/controllers/fui_checkbox_controller.js +48 -0
- data/app/javascript/ui/controllers/fui_dimmer_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_dropdown_controller.js +68 -0
- data/app/javascript/ui/controllers/fui_embed_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_flyout_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_form_controller.js +62 -0
- data/app/javascript/ui/controllers/fui_modal_controller.js +61 -0
- data/app/javascript/ui/controllers/fui_nag_controller.js +52 -0
- data/app/javascript/ui/controllers/fui_popup_controller.js +58 -0
- data/app/javascript/ui/controllers/fui_progress_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_rating_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_search_controller.js +76 -0
- data/app/javascript/ui/controllers/fui_shape_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_sidebar_controller.js +48 -0
- data/app/javascript/ui/controllers/fui_site_controller.js +29 -0
- data/app/javascript/ui/controllers/fui_slider_controller.js +53 -0
- data/app/javascript/ui/controllers/fui_state_controller.js +63 -0
- data/app/javascript/ui/controllers/fui_sticky_controller.js +50 -0
- data/app/javascript/ui/controllers/fui_tab_controller.js +57 -0
- data/app/javascript/ui/controllers/fui_toast_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_transition_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_visibility_controller.js +55 -0
- data/app/javascript/ui/index.js +114 -0
- data/app/javascript/visibility.js +1196 -0
- data/app/javascript/visibility.min.js +11 -0
- data/app/lib/component.rb +63 -0
- data/config/importmap.rb +27 -0
- data/config/initializers/ruby_template_handler.rb +31 -0
- data/config/routes.rb +2 -0
- data/lib/tasks/ui_tasks.rake +4 -0
- data/lib/ui/engine.rb +27 -0
- data/lib/ui/version.rb +3 -0
- data/lib/ui.rb +6 -0
- metadata +220 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Search — search component with local/remote data.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Search(placeholder: "Search...", name: "q")
|
|
7
|
+
# Search(category: true, fluid: true, size: :large)
|
|
8
|
+
|
|
9
|
+
class SearchComponent < Component
|
|
10
|
+
attribute :category, :boolean, default: false
|
|
11
|
+
attribute :placeholder, :string, default: "Search..."
|
|
12
|
+
attribute :min_characters, :integer, default: 1
|
|
13
|
+
attribute :fluid, :boolean, default: false
|
|
14
|
+
attribute :size, :string, default: nil
|
|
15
|
+
attribute :name, :string, default: nil
|
|
16
|
+
attribute :url, :string, default: nil
|
|
17
|
+
attribute :aligned, :string, default: nil
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
classes = class_names(
|
|
21
|
+
"ui",
|
|
22
|
+
size,
|
|
23
|
+
aligned && "#{aligned} aligned",
|
|
24
|
+
{ "category" => category,
|
|
25
|
+
"fluid" => fluid },
|
|
26
|
+
"search"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
data = { controller: "fui-search" }
|
|
30
|
+
data[:fui_search_url_value] = url if url
|
|
31
|
+
|
|
32
|
+
input_opts = { class: "prompt", type: "text", placeholder: placeholder }
|
|
33
|
+
input_opts[:name] = name if name
|
|
34
|
+
|
|
35
|
+
input_wrapper = tag.div(class: "ui icon input") {
|
|
36
|
+
safe_join([ tag.input(**input_opts), tag.i(class: "search icon") ])
|
|
37
|
+
}
|
|
38
|
+
results_el = tag.div(class: "results")
|
|
39
|
+
|
|
40
|
+
tag.div(class: classes, data: data) {
|
|
41
|
+
safe_join([ input_wrapper, results_el, @content ])
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Segment — grouped content sections.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Segment { text "Basic segment" }
|
|
7
|
+
# Segment(raised: true, padded: :very) { text "Raised" }
|
|
8
|
+
# Segment(inverted: true, color: :blue) { text "Blue inverted" }
|
|
9
|
+
|
|
10
|
+
class SegmentComponent < Component
|
|
11
|
+
include Attachable
|
|
12
|
+
include Sizeable
|
|
13
|
+
|
|
14
|
+
attribute :raised, :boolean, default: false
|
|
15
|
+
attribute :stacked, :boolean, default: false
|
|
16
|
+
attribute :piled, :boolean, default: false
|
|
17
|
+
attribute :vertical, :boolean, default: false
|
|
18
|
+
attribute :inverted, :boolean, default: false
|
|
19
|
+
attribute :padded, :string, default: nil
|
|
20
|
+
attribute :compact, :boolean, default: false
|
|
21
|
+
attribute :color, :string, default: nil
|
|
22
|
+
attribute :loading, :boolean, default: false
|
|
23
|
+
attribute :clearing, :boolean, default: false
|
|
24
|
+
attribute :basic, :boolean, default: false
|
|
25
|
+
attribute :circular, :boolean, default: false
|
|
26
|
+
attribute :disabled, :boolean, default: false
|
|
27
|
+
attribute :placeholder_seg, :boolean, default: false
|
|
28
|
+
attribute :secondary, :boolean, default: false
|
|
29
|
+
attribute :tertiary, :boolean, default: false
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
classes = class_names(
|
|
33
|
+
"ui",
|
|
34
|
+
size,
|
|
35
|
+
color,
|
|
36
|
+
padded && "#{padded == "very" ? "very " : ""}padded",
|
|
37
|
+
{ "attached" => attached,
|
|
38
|
+
"raised" => raised,
|
|
39
|
+
"stacked" => stacked,
|
|
40
|
+
"piled" => piled,
|
|
41
|
+
"vertical" => vertical,
|
|
42
|
+
"inverted" => inverted,
|
|
43
|
+
"compact" => compact,
|
|
44
|
+
"loading" => loading,
|
|
45
|
+
"clearing" => clearing,
|
|
46
|
+
"basic" => basic,
|
|
47
|
+
"circular" => circular,
|
|
48
|
+
"disabled" => disabled,
|
|
49
|
+
"placeholder" => placeholder_seg,
|
|
50
|
+
"secondary" => secondary,
|
|
51
|
+
"tertiary" => tertiary },
|
|
52
|
+
"segment"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
tag.div(class: classes) { @content }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SegmentGroup — wraps multiple segments into a visual group.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# SegmentGroup {
|
|
7
|
+
# Segment { text "Top" }
|
|
8
|
+
# Segment { text "Bottom" }
|
|
9
|
+
# }
|
|
10
|
+
#
|
|
11
|
+
# SegmentGroup(aligned: "horizontal") {
|
|
12
|
+
# Segment { text "Left" }
|
|
13
|
+
# Segment { text "Right" }
|
|
14
|
+
# }
|
|
15
|
+
|
|
16
|
+
class SegmentGroupComponent < Component
|
|
17
|
+
include Alignable
|
|
18
|
+
|
|
19
|
+
attribute :compact, :boolean, default: false
|
|
20
|
+
attribute :basic, :boolean, default: false
|
|
21
|
+
attribute :equal_width, :boolean, default: false
|
|
22
|
+
attribute :wrapping, :boolean, default: false
|
|
23
|
+
|
|
24
|
+
def to_s
|
|
25
|
+
classes = class_names(
|
|
26
|
+
"ui",
|
|
27
|
+
aligned,
|
|
28
|
+
{ "compact" => compact,
|
|
29
|
+
"basic" => basic, "equal width" => equal_width,
|
|
30
|
+
"wrapping" => wrapping },
|
|
31
|
+
"segments"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
tag.div(class: classes) { @content }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Shape — 3D CSS shape transformations.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Shape(type: :cube) {
|
|
7
|
+
# text '<div class="sides">'.html_safe
|
|
8
|
+
# text '<div class="side active">Side 1</div>'.html_safe
|
|
9
|
+
# text '<div class="side">Side 2</div>'.html_safe
|
|
10
|
+
# text '</div>'.html_safe
|
|
11
|
+
# }
|
|
12
|
+
|
|
13
|
+
class ShapeComponent < Component
|
|
14
|
+
attribute :type, :string, default: nil
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
classes = class_names(
|
|
18
|
+
"ui",
|
|
19
|
+
type,
|
|
20
|
+
"shape"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
tag.div(class: classes, data: { controller: "fui-shape" }) { @content }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Sidebar — slide-out sidebar navigation.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Sidebar(direction: :left, visible: true, inverted: true) {
|
|
7
|
+
# MenuItem(href: "#") { text "Home" }
|
|
8
|
+
# MenuItem(href: "#") { text "Settings" }
|
|
9
|
+
# }
|
|
10
|
+
|
|
11
|
+
class SidebarComponent < Component
|
|
12
|
+
attribute :direction, :string, default: "left"
|
|
13
|
+
attribute :transition, :string, default: "overlay"
|
|
14
|
+
attribute :visible, :boolean, default: false
|
|
15
|
+
attribute :inverted, :boolean, default: false
|
|
16
|
+
attribute :vertical, :boolean, default: true
|
|
17
|
+
attribute :width, :string, default: nil
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
classes = class_names(
|
|
21
|
+
"ui",
|
|
22
|
+
direction,
|
|
23
|
+
width,
|
|
24
|
+
{ "inverted" => inverted,
|
|
25
|
+
"vertical" => vertical,
|
|
26
|
+
"visible" => visible },
|
|
27
|
+
"sidebar",
|
|
28
|
+
"menu"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
tag.div(class: classes, data: { controller: "fui-sidebar", fui_sidebar_transition_value: transition }) { @content }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Site — base site wrapper with Fomantic-UI site module.
|
|
4
|
+
#
|
|
5
|
+
# Wraps content in a container that initializes the Fomantic-UI site module
|
|
6
|
+
# via the fui-site Stimulus controller.
|
|
7
|
+
|
|
8
|
+
class SiteComponent < Component
|
|
9
|
+
def to_s
|
|
10
|
+
tag.div(data: { controller: "fui-site" }) { @content }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Slider — range slider control.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Slider(min: 0, max: 100, value: 50, name: "volume")
|
|
7
|
+
# Slider(min: 0, max: 10, step: 1, labeled: true, color: :blue)
|
|
8
|
+
|
|
9
|
+
class SliderComponent < Component
|
|
10
|
+
attribute :min, :integer, default: 0
|
|
11
|
+
attribute :max, :integer, default: 100
|
|
12
|
+
attribute :value, :integer, default: 0
|
|
13
|
+
attribute :step, :integer, default: 1
|
|
14
|
+
attribute :labeled, :boolean, default: false
|
|
15
|
+
attribute :vertical, :boolean, default: false
|
|
16
|
+
attribute :reversed, :boolean, default: false
|
|
17
|
+
attribute :color, :string, default: nil
|
|
18
|
+
attribute :name, :string, default: nil
|
|
19
|
+
attribute :disabled, :boolean, default: false
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
classes = class_names(
|
|
23
|
+
"ui",
|
|
24
|
+
color,
|
|
25
|
+
{ "labeled" => labeled,
|
|
26
|
+
"vertical" => vertical,
|
|
27
|
+
"reversed" => reversed,
|
|
28
|
+
"disabled" => disabled },
|
|
29
|
+
"slider"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
data = {
|
|
33
|
+
controller: "fui-slider",
|
|
34
|
+
fui_slider_min_value: min,
|
|
35
|
+
fui_slider_max_value: max,
|
|
36
|
+
fui_slider_start_value: value,
|
|
37
|
+
fui_slider_step_value: step
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
name_el = name ? tag.input(type: "hidden", name: name, value: value) : nil
|
|
41
|
+
|
|
42
|
+
tag.div(class: classes, data: data) {
|
|
43
|
+
safe_join([ name_el, @content ])
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# State — UI state management for elements.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# State(text_active: "Following", text_inactive: "Follow") {
|
|
7
|
+
# Button { text "Follow" }
|
|
8
|
+
# }
|
|
9
|
+
|
|
10
|
+
class StateComponent < Component
|
|
11
|
+
attribute :text_active, :string, default: nil
|
|
12
|
+
attribute :text_inactive, :string, default: nil
|
|
13
|
+
attribute :class_active, :string, default: nil
|
|
14
|
+
attribute :class_inactive, :string, default: nil
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
data = { controller: "fui-state" }
|
|
18
|
+
data[:fui_state_text_active_value] = text_active if text_active
|
|
19
|
+
data[:fui_state_text_inactive_value] = text_inactive if text_inactive
|
|
20
|
+
data[:fui_state_class_active_value] = class_active if class_active
|
|
21
|
+
data[:fui_state_class_inactive_value] = class_inactive if class_inactive
|
|
22
|
+
|
|
23
|
+
tag.div(data: data) { @content }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Statistic — numeric statistics display.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Statistic(color: :blue) { |c|
|
|
7
|
+
# c.value { text "5,550" }
|
|
8
|
+
# c.label { text "Downloads" }
|
|
9
|
+
# }
|
|
10
|
+
# Statistic(horizontal: true) { |c|
|
|
11
|
+
# c.value { text "22" }
|
|
12
|
+
# c.label { text "Members" }
|
|
13
|
+
# }
|
|
14
|
+
|
|
15
|
+
class StatisticComponent < Component
|
|
16
|
+
attribute :horizontal, :boolean, default: false
|
|
17
|
+
attribute :color, :string, default: nil
|
|
18
|
+
attribute :size, :string, default: nil
|
|
19
|
+
attribute :inverted, :boolean, default: false
|
|
20
|
+
attribute :floated, :string, default: nil
|
|
21
|
+
|
|
22
|
+
slot :value
|
|
23
|
+
slot :label
|
|
24
|
+
|
|
25
|
+
def to_s
|
|
26
|
+
classes = class_names(
|
|
27
|
+
"ui",
|
|
28
|
+
color,
|
|
29
|
+
size,
|
|
30
|
+
floated && "#{floated} floated",
|
|
31
|
+
{ "horizontal" => horizontal,
|
|
32
|
+
"inverted" => inverted },
|
|
33
|
+
"statistic"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
value_el = @slots[:value] ? tag.div(class: "value") { @slots[:value] } : nil
|
|
37
|
+
label_el = @slots[:label] ? tag.div(class: "label") { @slots[:label] } : nil
|
|
38
|
+
|
|
39
|
+
tag.div(class: classes) {
|
|
40
|
+
safe_join([ value_el, label_el, @content.presence ])
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Step — individual step within a StepGroup.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# StepGroup {
|
|
7
|
+
# Step(active: true, icon: "truck", title: "Shipping", description: "Choose shipping")
|
|
8
|
+
# Step(title: "Billing", description: "Enter billing info")
|
|
9
|
+
# Step(disabled: true, title: "Confirm Order")
|
|
10
|
+
# }
|
|
11
|
+
#
|
|
12
|
+
# StepGroup {
|
|
13
|
+
# Step(completed: true) {
|
|
14
|
+
# text "Custom content"
|
|
15
|
+
# }
|
|
16
|
+
# }
|
|
17
|
+
|
|
18
|
+
class StepComponent < Component
|
|
19
|
+
attribute :active, :boolean, default: false
|
|
20
|
+
attribute :completed, :boolean, default: false
|
|
21
|
+
attribute :disabled, :boolean, default: false
|
|
22
|
+
attribute :icon, :string, default: nil
|
|
23
|
+
attribute :title, :string, default: nil
|
|
24
|
+
attribute :description, :string, default: nil
|
|
25
|
+
attribute :href, :string, default: nil
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
classes = class_names(
|
|
29
|
+
{ "active" => active, "completed" => completed, "disabled" => disabled },
|
|
30
|
+
"step"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
icon_el = icon ? tag.i(class: "#{icon} icon") : nil
|
|
34
|
+
|
|
35
|
+
content_parts = [
|
|
36
|
+
(title ? tag.div(class: "title") { title } : nil),
|
|
37
|
+
(description ? tag.div(class: "description") { description } : nil)
|
|
38
|
+
].compact
|
|
39
|
+
|
|
40
|
+
content_el = if content_parts.any?
|
|
41
|
+
tag.div(class: "content") { safe_join(content_parts) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
inner = if @content.present?
|
|
45
|
+
@content
|
|
46
|
+
else
|
|
47
|
+
safe_join([ icon_el, content_el ])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if href
|
|
51
|
+
tag.a(class: classes, href: href) { inner }
|
|
52
|
+
else
|
|
53
|
+
tag.div(class: classes) { inner }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# StepGroup — container for step indicators in multi-step workflows.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# StepGroup(ordered: true) {
|
|
7
|
+
# Step(active: true, title: "Shipping", description: "Choose your shipping options")
|
|
8
|
+
# Step(title: "Billing", description: "Enter billing information")
|
|
9
|
+
# Step(disabled: true, title: "Confirm Order")
|
|
10
|
+
# }
|
|
11
|
+
|
|
12
|
+
class StepGroupComponent < Component
|
|
13
|
+
attribute :ordered, :boolean, default: false
|
|
14
|
+
attribute :vertical, :boolean, default: false
|
|
15
|
+
attribute :fluid, :boolean, default: false
|
|
16
|
+
attribute :attached, :string, default: nil
|
|
17
|
+
attribute :unstackable, :boolean, default: false
|
|
18
|
+
attribute :size, :string, default: nil
|
|
19
|
+
attribute :stackable, :boolean, default: false
|
|
20
|
+
attribute :circular, :boolean, default: false
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
classes = class_names(
|
|
24
|
+
"ui",
|
|
25
|
+
size,
|
|
26
|
+
attached && "#{attached} attached",
|
|
27
|
+
{ "ordered" => ordered,
|
|
28
|
+
"vertical" => vertical,
|
|
29
|
+
"fluid" => fluid,
|
|
30
|
+
"unstackable" => unstackable,
|
|
31
|
+
"stackable" => stackable,
|
|
32
|
+
"circular" => circular },
|
|
33
|
+
"steps"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
tag.div(class: classes) { @content }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Sticky — sticky/fixed position elements that follow scroll.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Sticky { text "I stick on scroll" }
|
|
7
|
+
# Sticky(offset: 50, pushing: true) { text "Sticky header" }
|
|
8
|
+
|
|
9
|
+
class StickyComponent < Component
|
|
10
|
+
attribute :context, :string, default: nil
|
|
11
|
+
attribute :pushing, :boolean, default: false
|
|
12
|
+
attribute :offset, :integer, default: 0
|
|
13
|
+
|
|
14
|
+
def to_s
|
|
15
|
+
data = { controller: "fui-sticky" }
|
|
16
|
+
data[:fui_sticky_context_value] = context if context
|
|
17
|
+
data[:fui_sticky_pushing_value] = "true" if pushing
|
|
18
|
+
data[:fui_sticky_offset_value] = offset if offset > 0
|
|
19
|
+
|
|
20
|
+
tag.div(class: "ui sticky", data: data) { @content }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SubHeader — sub header text within a Header.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Header(size: :h2) {
|
|
7
|
+
# text "Main Title"
|
|
8
|
+
# SubHeader { text "A subtitle or description" }
|
|
9
|
+
# }
|
|
10
|
+
|
|
11
|
+
class SubHeaderComponent < Component
|
|
12
|
+
def to_s
|
|
13
|
+
tag.div(class: "sub header") { @content }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SubMenu — sub-menu or positioned menu group within a Menu.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Menu {
|
|
7
|
+
# MenuItem(href: "/") { text "Home" }
|
|
8
|
+
# SubMenu(position: "right") {
|
|
9
|
+
# MenuItem(href: "/login") { text "Login" }
|
|
10
|
+
# }
|
|
11
|
+
# }
|
|
12
|
+
|
|
13
|
+
class SubMenuComponent < Component
|
|
14
|
+
include Positionable
|
|
15
|
+
|
|
16
|
+
def to_s
|
|
17
|
+
classes = class_names(
|
|
18
|
+
position,
|
|
19
|
+
"menu"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
tag.div(class: classes) { @content }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Tab — tab navigation with content panes.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Tab(active: true) { text "Tab pane content" }
|
|
7
|
+
|
|
8
|
+
class TabComponent < Component
|
|
9
|
+
attribute :active, :boolean, default: false
|
|
10
|
+
attribute :path, :string, default: nil
|
|
11
|
+
|
|
12
|
+
def to_s
|
|
13
|
+
classes = class_names(
|
|
14
|
+
"ui",
|
|
15
|
+
{ "active" => active },
|
|
16
|
+
"tab"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
data = { controller: "fui-tab" }
|
|
20
|
+
data[:tab] = path if path
|
|
21
|
+
|
|
22
|
+
tag.div(class: classes, data: data) { @content }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# TableCell — a table cell (td or th).
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# TableRow {
|
|
7
|
+
# TableCell { text "Data" }
|
|
8
|
+
# TableCell(aligned: "right", collapsing: true) { text "10 hours ago" }
|
|
9
|
+
# TableCell(heading: true, colspan: 3) { text "Section" }
|
|
10
|
+
# }
|
|
11
|
+
|
|
12
|
+
class TableCellComponent < Component
|
|
13
|
+
attribute :heading, :boolean, default: false
|
|
14
|
+
attribute :aligned, :string, default: nil
|
|
15
|
+
attribute :collapsing, :boolean, default: false
|
|
16
|
+
attribute :single_line, :boolean, default: false
|
|
17
|
+
attribute :positive, :boolean, default: false
|
|
18
|
+
attribute :negative, :boolean, default: false
|
|
19
|
+
attribute :warning, :boolean, default: false
|
|
20
|
+
attribute :error, :boolean, default: false
|
|
21
|
+
attribute :active, :boolean, default: false
|
|
22
|
+
attribute :disabled, :boolean, default: false
|
|
23
|
+
attribute :selectable, :boolean, default: false
|
|
24
|
+
attribute :color, :string, default: nil
|
|
25
|
+
attribute :width, :integer, default: nil
|
|
26
|
+
attribute :colspan, :integer, default: nil
|
|
27
|
+
attribute :rowspan, :integer, default: nil
|
|
28
|
+
|
|
29
|
+
NUMBERS = %w[one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen].freeze
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
width_word = width && width.between?(1, 16) ? NUMBERS[width - 1] : nil
|
|
33
|
+
|
|
34
|
+
classes = [
|
|
35
|
+
(aligned && "#{aligned} aligned"),
|
|
36
|
+
("collapsing" if collapsing),
|
|
37
|
+
("single line" if single_line),
|
|
38
|
+
("positive" if positive),
|
|
39
|
+
("negative" if negative),
|
|
40
|
+
("warning" if warning),
|
|
41
|
+
("error" if error),
|
|
42
|
+
("active" if active),
|
|
43
|
+
("disabled" if disabled),
|
|
44
|
+
("selectable" if selectable),
|
|
45
|
+
color,
|
|
46
|
+
(width_word && "#{width_word} wide")
|
|
47
|
+
].compact
|
|
48
|
+
|
|
49
|
+
opts = {}
|
|
50
|
+
opts[:class] = classes.join(" ") if classes.any?
|
|
51
|
+
opts[:colspan] = colspan if colspan
|
|
52
|
+
opts[:rowspan] = rowspan if rowspan
|
|
53
|
+
|
|
54
|
+
if heading
|
|
55
|
+
tag.th(**opts) { @content }
|
|
56
|
+
else
|
|
57
|
+
tag.td(**opts) { @content }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|