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,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# List — ordered, unordered, and bulleted lists.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# List(bulleted: true) { text "items..." }
|
|
7
|
+
# List(divided: true, relaxed: true) { text "items..." }
|
|
8
|
+
|
|
9
|
+
class ListComponent < Component
|
|
10
|
+
attribute :ordered, :boolean, default: false
|
|
11
|
+
attribute :bulleted, :boolean, default: false
|
|
12
|
+
attribute :divided, :boolean, default: false
|
|
13
|
+
attribute :relaxed, :boolean, default: false
|
|
14
|
+
attribute :animated, :boolean, default: false
|
|
15
|
+
attribute :horizontal, :boolean, default: false
|
|
16
|
+
attribute :inverted, :boolean, default: false
|
|
17
|
+
attribute :size, :string, default: nil
|
|
18
|
+
attribute :celled, :boolean, default: false
|
|
19
|
+
attribute :selection, :boolean, default: false
|
|
20
|
+
attribute :link, :boolean, default: false
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
classes = class_names(
|
|
24
|
+
"ui",
|
|
25
|
+
size,
|
|
26
|
+
{ "ordered" => ordered, "bulleted" => bulleted, "divided" => divided,
|
|
27
|
+
"relaxed" => relaxed, "animated" => animated, "horizontal" => horizontal,
|
|
28
|
+
"inverted" => inverted, "celled" => celled, "selection" => selection,
|
|
29
|
+
"link" => link },
|
|
30
|
+
"list"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if ordered
|
|
34
|
+
tag.ol(class: classes) { @content }
|
|
35
|
+
else
|
|
36
|
+
tag.div(class: classes) { @content }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Loader — loading spinners.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Loader(active: true)
|
|
7
|
+
# Loader(active: true, size: :large) { text "Loading..." }
|
|
8
|
+
# Loader(inline: true, centered: true, active: true)
|
|
9
|
+
|
|
10
|
+
class LoaderComponent < Component
|
|
11
|
+
attribute :active, :boolean, default: false
|
|
12
|
+
attribute :inline, :boolean, default: false
|
|
13
|
+
attribute :centered, :boolean, default: false
|
|
14
|
+
attribute :size, :string, default: nil
|
|
15
|
+
attribute :inverted, :boolean, default: false
|
|
16
|
+
attribute :indeterminate, :boolean, default: false
|
|
17
|
+
attribute :color, :string, default: nil
|
|
18
|
+
attribute :disabled, :boolean, default: false
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
classes = class_names(
|
|
22
|
+
"ui",
|
|
23
|
+
size,
|
|
24
|
+
color,
|
|
25
|
+
{ "active" => active, "disabled" => disabled, "inline" => inline,
|
|
26
|
+
"centered" => centered, "inverted" => inverted,
|
|
27
|
+
"indeterminate" => indeterminate, "text" => @content.present? },
|
|
28
|
+
"loader"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
tag.div(class: classes) { @content }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Menu — navigation menus.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Menu(pointing: true, secondary: true) {
|
|
7
|
+
# MenuItem(href: "#", active: true) { text "Home" }
|
|
8
|
+
# MenuItem(href: "#") { text "Messages" }
|
|
9
|
+
# }
|
|
10
|
+
|
|
11
|
+
class MenuComponent < Component
|
|
12
|
+
include Positionable
|
|
13
|
+
include Attachable
|
|
14
|
+
include Sizeable
|
|
15
|
+
|
|
16
|
+
attribute :secondary, :boolean, default: false
|
|
17
|
+
attribute :pointing, :boolean, default: false
|
|
18
|
+
attribute :tabular, :boolean, default: false
|
|
19
|
+
attribute :vertical, :boolean, default: false
|
|
20
|
+
attribute :fixed, :string, default: nil
|
|
21
|
+
attribute :inverted, :boolean, default: false
|
|
22
|
+
attribute :icon, :boolean, default: false
|
|
23
|
+
attribute :labeled_icon, :boolean, default: false
|
|
24
|
+
attribute :compact, :boolean, default: false
|
|
25
|
+
attribute :fluid, :boolean, default: false
|
|
26
|
+
attribute :color, :string, default: nil
|
|
27
|
+
attribute :stackable, :boolean, default: false
|
|
28
|
+
attribute :text, :boolean, default: false
|
|
29
|
+
attribute :pagination, :boolean, default: false
|
|
30
|
+
attribute :borderless, :boolean, default: false
|
|
31
|
+
attribute :items, :integer, default: nil
|
|
32
|
+
|
|
33
|
+
NUMBERS = %w[one two three four five six seven eight nine ten eleven twelve].freeze
|
|
34
|
+
|
|
35
|
+
def to_s
|
|
36
|
+
item_word = items && items.between?(1, 12) ? NUMBERS[items - 1] : nil
|
|
37
|
+
|
|
38
|
+
classes = class_names(
|
|
39
|
+
"ui",
|
|
40
|
+
position,
|
|
41
|
+
size,
|
|
42
|
+
color,
|
|
43
|
+
item_word && "#{item_word} item",
|
|
44
|
+
fixed && "#{fixed} fixed",
|
|
45
|
+
{ "attached" => attached,
|
|
46
|
+
"secondary" => secondary,
|
|
47
|
+
"pointing" => pointing,
|
|
48
|
+
"tabular" => tabular,
|
|
49
|
+
"vertical" => vertical,
|
|
50
|
+
"inverted" => inverted,
|
|
51
|
+
"icon" => icon && !labeled_icon,
|
|
52
|
+
"labeled icon" => labeled_icon,
|
|
53
|
+
"compact" => compact,
|
|
54
|
+
"fluid" => fluid,
|
|
55
|
+
"stackable" => stackable,
|
|
56
|
+
"text" => text,
|
|
57
|
+
"pagination" => pagination,
|
|
58
|
+
"borderless" => borderless },
|
|
59
|
+
"menu"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
tag.div(class: classes) { @content }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# MenuItem — individual item within a Menu or Sidebar.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Menu {
|
|
7
|
+
# MenuItem(href: "/") { text "Home" }
|
|
8
|
+
# MenuItem(active: true) { text "Current" }
|
|
9
|
+
# MenuItem(header: true) { text "Section Header" }
|
|
10
|
+
# MenuItem(icon: "settings") { text "Settings" }
|
|
11
|
+
# }
|
|
12
|
+
|
|
13
|
+
class MenuItemComponent < Component
|
|
14
|
+
include Positionable
|
|
15
|
+
|
|
16
|
+
attribute :href, :string, default: nil
|
|
17
|
+
attribute :active, :boolean, default: false
|
|
18
|
+
attribute :disabled, :boolean, default: false
|
|
19
|
+
attribute :header, :boolean, default: false
|
|
20
|
+
attribute :icon, :string, default: nil
|
|
21
|
+
attribute :fitted, :string, default: nil
|
|
22
|
+
attribute :link, :boolean, default: false
|
|
23
|
+
attribute :color, :string, default: nil
|
|
24
|
+
attribute :dropdown, :boolean, default: false
|
|
25
|
+
attribute :value, :string, default: nil
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
classes = class_names(
|
|
29
|
+
color,
|
|
30
|
+
fitted && (fitted == "true" ? "fitted" : "#{fitted} fitted"),
|
|
31
|
+
position,
|
|
32
|
+
{ "active" => active,
|
|
33
|
+
"disabled" => disabled,
|
|
34
|
+
"header" => header,
|
|
35
|
+
"link" => link,
|
|
36
|
+
"dropdown" => dropdown },
|
|
37
|
+
"item"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
icon_el = icon ? tag.i(class: "#{icon} icon") : nil
|
|
41
|
+
inner = icon_el ? safe_join([ icon_el, @content ]) : @content
|
|
42
|
+
|
|
43
|
+
opts = { class: classes }
|
|
44
|
+
opts["data-value"] = value if value
|
|
45
|
+
|
|
46
|
+
if href
|
|
47
|
+
tag.a(**opts, href: href) { inner }
|
|
48
|
+
else
|
|
49
|
+
tag.div(**opts) { inner }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Message — alert/info messages.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Message(type: :success) { text "It worked!" }
|
|
7
|
+
# Message(type: :error, icon: "exclamation triangle") { |c|
|
|
8
|
+
# c.header { text "Error" }
|
|
9
|
+
# text "Something went wrong."
|
|
10
|
+
# }
|
|
11
|
+
# Message(dismissible: true) { text "Notice" }
|
|
12
|
+
|
|
13
|
+
class MessageComponent < Component
|
|
14
|
+
include Attachable
|
|
15
|
+
|
|
16
|
+
attribute :type, :string, default: nil
|
|
17
|
+
attribute :icon, :string, default: nil
|
|
18
|
+
attribute :dismissible, :boolean, default: false
|
|
19
|
+
attribute :floating, :boolean, default: false
|
|
20
|
+
attribute :compact, :boolean, default: false
|
|
21
|
+
attribute :color, :string, default: nil
|
|
22
|
+
attribute :size, :string, default: nil
|
|
23
|
+
attribute :hidden, :boolean, default: false
|
|
24
|
+
attribute :visible, :boolean, default: false
|
|
25
|
+
|
|
26
|
+
slot :header
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
classes = class_names(
|
|
30
|
+
"ui",
|
|
31
|
+
size,
|
|
32
|
+
color,
|
|
33
|
+
type,
|
|
34
|
+
{ "attached" => attached,
|
|
35
|
+
"icon" => icon,
|
|
36
|
+
"floating" => floating,
|
|
37
|
+
"compact" => compact,
|
|
38
|
+
"hidden" => hidden,
|
|
39
|
+
"visible" => visible },
|
|
40
|
+
"message"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
close_el = dismissible ? tag.i(class: "close icon") : nil
|
|
44
|
+
icon_el = icon ? tag.i(class: "#{icon} icon") : nil
|
|
45
|
+
header_el = @slots[:header] ? tag.div(class: "header") { @slots[:header] } : nil
|
|
46
|
+
|
|
47
|
+
content_parts = safe_join([ header_el, @content.presence ])
|
|
48
|
+
content_wrapper = icon ? tag.div(class: "content") { content_parts } : content_parts
|
|
49
|
+
|
|
50
|
+
tag.div(class: classes) {
|
|
51
|
+
safe_join([ close_el, icon_el, content_wrapper ])
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Modal — dialog windows with dimmer.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Modal(size: :small) { |c|
|
|
7
|
+
# c.header { text "Confirm Action" }
|
|
8
|
+
# c.content { text "Are you sure?" }
|
|
9
|
+
# c.actions {
|
|
10
|
+
# Button(variant: :deny) { text "Cancel" }
|
|
11
|
+
# Button(variant: :approve, color: :green) { text "OK" }
|
|
12
|
+
# }
|
|
13
|
+
# }
|
|
14
|
+
|
|
15
|
+
class ModalComponent < Component
|
|
16
|
+
attribute :size, :string, default: nil
|
|
17
|
+
attribute :basic, :boolean, default: false
|
|
18
|
+
attribute :closable, :boolean, default: true
|
|
19
|
+
attribute :blurring, :boolean, default: false
|
|
20
|
+
attribute :longer, :boolean, default: false
|
|
21
|
+
attribute :fullscreen, :boolean, default: false
|
|
22
|
+
|
|
23
|
+
slot :header
|
|
24
|
+
slot :content
|
|
25
|
+
slot :actions
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
classes = class_names(
|
|
29
|
+
"ui",
|
|
30
|
+
size,
|
|
31
|
+
{ "basic" => basic,
|
|
32
|
+
"longer" => longer,
|
|
33
|
+
"fullscreen" => fullscreen },
|
|
34
|
+
"modal"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
data = { controller: "fui-modal" }
|
|
38
|
+
data[:fui_modal_closable_value] = "false" unless closable
|
|
39
|
+
data[:fui_modal_blurring_value] = "true" if blurring
|
|
40
|
+
|
|
41
|
+
close_el = closable ? tag.i(class: "close icon") : nil
|
|
42
|
+
header_el = @slots[:header] ? tag.div(class: "header") { @slots[:header] } : nil
|
|
43
|
+
content_el = @slots[:content] ? tag.div(class: "content") { @slots[:content] } : nil
|
|
44
|
+
actions_el = @slots[:actions] ? tag.div(class: "actions") { @slots[:actions] } : nil
|
|
45
|
+
|
|
46
|
+
tag.div(class: classes, data: data) {
|
|
47
|
+
safe_join([ close_el, header_el, content_el, @content.presence, actions_el ])
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Nag — persistent notification/cookie nag bar.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Nag { text "We use cookies." }
|
|
7
|
+
# Nag(fixed: true) { text "Update available!" }
|
|
8
|
+
|
|
9
|
+
class NagComponent < Component
|
|
10
|
+
attribute :fixed, :boolean, default: false
|
|
11
|
+
|
|
12
|
+
def to_s
|
|
13
|
+
classes = class_names(
|
|
14
|
+
"ui",
|
|
15
|
+
{ "fixed" => fixed },
|
|
16
|
+
"nag"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
close_el = tag.i(class: "close icon")
|
|
20
|
+
|
|
21
|
+
tag.div(class: classes, data: { controller: "fui-nag" }) {
|
|
22
|
+
safe_join([ close_el, @content ])
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Overlay — floating overlay wrapper for positioned content.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Overlay {
|
|
7
|
+
# Menu(vertical: true, labeled_icon: true) {
|
|
8
|
+
# MenuItem(href: "#", icon: "twitter") { text "Tweet" }
|
|
9
|
+
# }
|
|
10
|
+
# }
|
|
11
|
+
|
|
12
|
+
class OverlayComponent < Component
|
|
13
|
+
def to_s
|
|
14
|
+
tag.div(class: "overlay") { @content }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Placeholder — skeleton/placeholder content while loading.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Placeholder { |c|
|
|
7
|
+
# c.header_slot {
|
|
8
|
+
# text '<div class="line"></div><div class="line"></div>'.html_safe
|
|
9
|
+
# }
|
|
10
|
+
# c.paragraph {
|
|
11
|
+
# text '<div class="line"></div><div class="line"></div>'.html_safe
|
|
12
|
+
# }
|
|
13
|
+
# }
|
|
14
|
+
|
|
15
|
+
class PlaceholderComponent < Component
|
|
16
|
+
attribute :fluid, :boolean, default: false
|
|
17
|
+
attribute :inverted, :boolean, default: false
|
|
18
|
+
|
|
19
|
+
slot :header_slot
|
|
20
|
+
slot :paragraph
|
|
21
|
+
slot :image_slot
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
classes = class_names(
|
|
25
|
+
"ui",
|
|
26
|
+
{ "fluid" => fluid,
|
|
27
|
+
"inverted" => inverted },
|
|
28
|
+
"placeholder"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
header_el = @slots[:header_slot] ? tag.div(class: "header") { @slots[:header_slot] } : nil
|
|
32
|
+
para_el = @slots[:paragraph] ? tag.div(class: "paragraph") { @slots[:paragraph] } : nil
|
|
33
|
+
image_el = @slots[:image_slot] ? tag.div(class: "image") { @slots[:image_slot] } : nil
|
|
34
|
+
|
|
35
|
+
tag.div(class: classes) {
|
|
36
|
+
safe_join([ header_el, para_el, image_el, @content.presence ])
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Popup — tooltips and popup content.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Popup(content: "Tooltip text", position: "top center") {
|
|
7
|
+
# Button { text "Hover me" }
|
|
8
|
+
# }
|
|
9
|
+
# Popup(hoverable: true) { text "Hover for popup" }
|
|
10
|
+
|
|
11
|
+
class PopupComponent < Component
|
|
12
|
+
include Positionable
|
|
13
|
+
default position: "top center"
|
|
14
|
+
|
|
15
|
+
attribute :content, :string, default: nil
|
|
16
|
+
attribute :title, :string, default: nil
|
|
17
|
+
attribute :variation, :string, default: nil
|
|
18
|
+
attribute :hoverable, :boolean, default: false
|
|
19
|
+
attribute :on, :string, default: "hover"
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
data = { controller: "fui-popup", fui_popup_position_value: position }
|
|
23
|
+
data[:fui_popup_content_value] = content if content
|
|
24
|
+
data[:fui_popup_title_value] = title if title
|
|
25
|
+
data[:fui_popup_hoverable_value] = "true" if hoverable
|
|
26
|
+
data[:fui_popup_variation_value] = variation if variation
|
|
27
|
+
data[:fui_popup_on_value] = on if on != "hover"
|
|
28
|
+
|
|
29
|
+
tag.span(data: data) { @content }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Progress — progress bars.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Progress(value: 65, total: 100, color: :green, active: true) { |c|
|
|
7
|
+
# c.bar { }
|
|
8
|
+
# c.label { text "65% Complete" }
|
|
9
|
+
# }
|
|
10
|
+
# Progress(value: 3, total: 10, indicating: true)
|
|
11
|
+
|
|
12
|
+
class ProgressComponent < Component
|
|
13
|
+
attribute :value, :integer, default: 0
|
|
14
|
+
attribute :total, :integer, default: 100
|
|
15
|
+
attribute :indicating, :boolean, default: false
|
|
16
|
+
attribute :active, :boolean, default: false
|
|
17
|
+
attribute :color, :string, default: nil
|
|
18
|
+
attribute :size, :string, default: nil
|
|
19
|
+
attribute :attached, :string, default: nil
|
|
20
|
+
attribute :inverted, :boolean, default: false
|
|
21
|
+
attribute :disabled, :boolean, default: false
|
|
22
|
+
|
|
23
|
+
slot :bar
|
|
24
|
+
slot :label
|
|
25
|
+
|
|
26
|
+
def to_s
|
|
27
|
+
percent = total > 0 ? ((value.to_f / total) * 100).round : 0
|
|
28
|
+
|
|
29
|
+
classes = class_names(
|
|
30
|
+
"ui",
|
|
31
|
+
color,
|
|
32
|
+
size,
|
|
33
|
+
attached && "#{attached} attached",
|
|
34
|
+
{ "indicating" => indicating,
|
|
35
|
+
"active" => active,
|
|
36
|
+
"inverted" => inverted,
|
|
37
|
+
"disabled" => disabled },
|
|
38
|
+
"progress"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
bar_el = tag.div(class: "bar", style: "width:#{percent}%") { @slots[:bar] }
|
|
42
|
+
label_el = @slots[:label] ? tag.div(class: "label") { @slots[:label] } : nil
|
|
43
|
+
|
|
44
|
+
tag.div(class: classes, data: { controller: "fui-progress", percent: percent }) {
|
|
45
|
+
safe_join([ bar_el, label_el, @content.presence ])
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Pusher — main content wrapper for Sidebar layouts.
|
|
4
|
+
# The pusher wraps the page content that gets pushed when a sidebar opens.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# Sidebar(inverted: true) {
|
|
8
|
+
# MenuItem(href: "/") { text "Home" }
|
|
9
|
+
# }
|
|
10
|
+
# Pusher {
|
|
11
|
+
# text "Main content here"
|
|
12
|
+
# }
|
|
13
|
+
|
|
14
|
+
class PusherComponent < Component
|
|
15
|
+
def to_s
|
|
16
|
+
tag.div(class: "pusher") { @content }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Rail — content rails floating alongside main content.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Rail(position: :left) { text "Side content" }
|
|
7
|
+
# Rail(position: :right, close: true) { text "Close rail" }
|
|
8
|
+
|
|
9
|
+
class RailComponent < Component
|
|
10
|
+
include Positionable
|
|
11
|
+
default position: "left"
|
|
12
|
+
|
|
13
|
+
attribute :close, :boolean, default: false
|
|
14
|
+
attribute :attached, :boolean, default: false
|
|
15
|
+
attribute :dividing, :boolean, default: false
|
|
16
|
+
attribute :internal, :boolean, default: false
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
classes = class_names(
|
|
20
|
+
"ui",
|
|
21
|
+
position,
|
|
22
|
+
{ "close" => close,
|
|
23
|
+
"attached" => attached,
|
|
24
|
+
"dividing" => dividing,
|
|
25
|
+
"internal" => internal },
|
|
26
|
+
"rail"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
tag.div(class: classes) { @content }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Rating — star/heart rating widget.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Rating(max_rating: 5, rating: 3)
|
|
7
|
+
# Rating(max_rating: 5, rating: 4, icon: :heart, size: :large)
|
|
8
|
+
# Rating(max_rating: 10, disabled: true, rating: 7)
|
|
9
|
+
|
|
10
|
+
class RatingComponent < Component
|
|
11
|
+
attribute :max_rating, :integer, default: 5
|
|
12
|
+
attribute :rating, :integer, default: 0
|
|
13
|
+
attribute :icon, :string, default: "star"
|
|
14
|
+
attribute :size, :string, default: nil
|
|
15
|
+
attribute :disabled, :boolean, default: false
|
|
16
|
+
attribute :clearable, :boolean, default: false
|
|
17
|
+
attribute :name, :string, default: nil
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
classes = class_names(
|
|
21
|
+
"ui",
|
|
22
|
+
icon,
|
|
23
|
+
size,
|
|
24
|
+
{ "disabled" => disabled },
|
|
25
|
+
"rating"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
data = {
|
|
29
|
+
controller: "fui-rating",
|
|
30
|
+
fui_rating_max_rating_value: max_rating,
|
|
31
|
+
fui_rating_initial_rating_value: rating
|
|
32
|
+
}
|
|
33
|
+
data[:fui_rating_clearable_value] = "true" if clearable
|
|
34
|
+
|
|
35
|
+
name_el = name ? tag.input(type: "hidden", name: name, value: rating) : nil
|
|
36
|
+
|
|
37
|
+
tag.div(class: classes, data: data) {
|
|
38
|
+
safe_join([ name_el, @content ])
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Reset — CSS reset/normalize.
|
|
4
|
+
#
|
|
5
|
+
# Fomantic-UI's reset is loaded via the asset pipeline (semantic.css).
|
|
6
|
+
# This component is a no-op marker for inventory completeness.
|
|
7
|
+
|
|
8
|
+
class ResetComponent < Component
|
|
9
|
+
def to_s
|
|
10
|
+
tag.comment("fomantic-ui reset loaded via asset pipeline")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Reveal — hidden content revealed on hover/active.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Reveal(type: :fade) { |c|
|
|
7
|
+
# c.visible { Image(src: "before.jpg") }
|
|
8
|
+
# c.hidden { Image(src: "after.jpg") }
|
|
9
|
+
# }
|
|
10
|
+
|
|
11
|
+
class RevealComponent < Component
|
|
12
|
+
attribute :type, :string, default: "fade"
|
|
13
|
+
attribute :active, :boolean, default: false
|
|
14
|
+
attribute :instant, :boolean, default: false
|
|
15
|
+
attribute :disabled, :boolean, default: false
|
|
16
|
+
attribute :move_direction, :string, default: nil
|
|
17
|
+
|
|
18
|
+
slot :visible
|
|
19
|
+
slot :hidden
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
classes = class_names(
|
|
23
|
+
"ui",
|
|
24
|
+
type,
|
|
25
|
+
(type == "move") && move_direction,
|
|
26
|
+
{ "active" => active,
|
|
27
|
+
"instant" => instant,
|
|
28
|
+
"disabled" => disabled },
|
|
29
|
+
"reveal"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
visible_el = @slots[:visible] ? tag.div(class: "visible content") { @slots[:visible] } : nil
|
|
33
|
+
hidden_el = @slots[:hidden] ? tag.div(class: "hidden content") { @slots[:hidden] } : nil
|
|
34
|
+
|
|
35
|
+
tag.div(class: classes) {
|
|
36
|
+
safe_join([ visible_el, hidden_el, @content ])
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Row — grid row with optional column count.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Grid {
|
|
7
|
+
# Row(columns: 3) {
|
|
8
|
+
# Column { text "A" }
|
|
9
|
+
# Column { text "B" }
|
|
10
|
+
# Column { text "C" }
|
|
11
|
+
# }
|
|
12
|
+
# }
|
|
13
|
+
|
|
14
|
+
class RowComponent < Component
|
|
15
|
+
NUMBERS = %w[one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen].freeze
|
|
16
|
+
|
|
17
|
+
attribute :columns, :integer, default: nil
|
|
18
|
+
attribute :centered, :boolean, default: false
|
|
19
|
+
attribute :stretched, :boolean, default: false
|
|
20
|
+
attribute :equal_width, :boolean, default: false
|
|
21
|
+
attribute :only, :string, default: nil
|
|
22
|
+
attribute :aligned, :string, default: nil
|
|
23
|
+
|
|
24
|
+
def to_s
|
|
25
|
+
col_word = columns && columns.between?(1, 16) ? NUMBERS[columns - 1] : nil
|
|
26
|
+
|
|
27
|
+
classes = class_names(
|
|
28
|
+
col_word && "#{col_word} column",
|
|
29
|
+
only && "#{only} only",
|
|
30
|
+
aligned && "#{aligned} aligned",
|
|
31
|
+
{ "centered" => centered,
|
|
32
|
+
"stretched" => stretched,
|
|
33
|
+
"equal width" => equal_width },
|
|
34
|
+
"row"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
tag.div(class: classes) { @content }
|
|
38
|
+
end
|
|
39
|
+
end
|