Module: Ruflet::Rails::ViewHelpers
- Defined in:
- lib/ruflet/rails/view_helpers.rb
Overview
ERB view helpers for dropping a Ruflet native UI into a server-rendered Rails page. Auto-included into ActionView (see Railtie), so they are available in any .erb template.
A Ruflet web frontend is a Flutter app mounted at a route (see Ruflet::Rails.web_app in config/routes.rb). To embed that native UI inside an HTML page, render it in an isolated frame pointed at the mount:
<%= ruflet_frame "/products", height: 640 %>
<%= ruflet_frame "/showcase", height: "80vh", width: "100%" %>
The frame is same-origin by default (a relative path), so the Ruflet WebSocket and assets resolve against this host with no extra config. Pass a full URL to embed a Ruflet app on another host.
Instance Method Summary collapse
-
#ruflet_appbar(title = nil, payload: {}, leading: nil, actions: nil, **attrs, &block) ⇒ Object
A header the native shell hides and re-renders as a native AppBar.
-
#ruflet_appbar_action(icon, href = nil, nav: :push, payload: {}, **attrs) ⇒ Object
An AppBar action button (icon taps navigate).
-
#ruflet_bottom_nav(name: "bottom-navigation", payload: {}, **attrs, &block) ⇒ Object
A nav the native shell hides and re-renders as a native bottom NavigationBar.
- #ruflet_copy_button(label, text:, toast: "Copied", haptic: true, **attrs) ⇒ Object
-
#ruflet_drawer(action: :root, payload: {}, **attrs, &block) ⇒ Object
A drawer the native shell hides and re-renders as a native NavigationDrawer.
-
#ruflet_drawer_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_drawer.
-
#ruflet_frame(path, height: 600, width: "100%", title: "Ruflet", style: nil, **attrs) ⇒ Object
Embed a mounted Ruflet route as an isolated, responsive frame.
- #ruflet_haptic_button(label, style: "selection", **attrs) ⇒ Object
- #ruflet_launch_link(label, href, mode: nil, **attrs) ⇒ Object
-
#ruflet_nav_item(label, href, icon:, selected: false, color: nil, size: 24, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_bottom_nav.
-
#ruflet_navigation_rail(action: :root, extended: nil, label_type: nil, breakpoint: nil, payload: {}, **attrs, &block) ⇒ Object
(also: #ruflet_rail)
Desktop/tablet navigation the native shell hides and re-renders as a native NavigationRail beside the WebView body.
-
#ruflet_rail_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_navigation_rail.
-
#ruflet_share_link(label, href = "#", text: nil, title: nil, subject: nil, url: nil, files: nil, **attrs) ⇒ Object
Native platform services from ERB.
Instance Method Details
#ruflet_appbar(title = nil, payload: {}, leading: nil, actions: nil, **attrs, &block) ⇒ Object
A header the native shell hides and re-renders as a native AppBar. Place
action items inside with ruflet-icon (use ruflet_appbar_action).
<%= ruflet_appbar "Inbox" do %>
<%= ruflet_appbar_action "search", search_path %>
<% end %>
62 63 64 65 66 67 68 69 70 |
# File 'lib/ruflet/rails/view_helpers.rb', line 62 def (title = nil, payload: {}, leading: nil, actions: nil, **attrs, &block) = ruflet_stringify_keys(payload) ["leading"] = ruflet_stringify_keys(leading) unless leading.nil? ["actions"] = ruflet_stringify_keys(actions) unless actions.nil? data = { "data-ruflet-appbar" => .empty? ? "" : ruflet_json(), "data-ruflet-title" => title, "hidden" => true } ruflet_build_tag("header", ruflet_capture(&block), data.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_appbar_action(icon, href = nil, nav: :push, payload: {}, **attrs) ⇒ Object
An AppBar action button (icon taps navigate).
73 74 75 76 77 |
# File 'lib/ruflet/rails/view_helpers.rb', line 73 def (icon, href = nil, nav: :push, payload: {}, **attrs) payload = ruflet_compact_hash({ "icon" => icon, "action" => nav.to_s }.merge(ruflet_stringify_keys(payload))) data = { "data-ruflet-icon" => ruflet_json(payload), "href" => href } ruflet_build_tag("a", "", data.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_bottom_nav(name: "bottom-navigation", payload: {}, **attrs, &block) ⇒ Object
A nav the native shell hides and re-renders as a native bottom
NavigationBar. Items are ruflet_nav_item links.
<%= ruflet_bottom_nav do %>
<%= ruflet_nav_item "Home", root_path, icon: "house", selected: true %>
<%= ruflet_nav_item "Profile", profile_path, icon: "person" %>
<% end %>
86 87 88 89 90 91 92 |
# File 'lib/ruflet/rails/view_helpers.rb', line 86 def ruflet_bottom_nav(name: "bottom-navigation", payload: {}, **attrs, &block) nav_payload = ruflet_stringify_keys(payload) ruflet_build_tag("nav", ruflet_capture(&block), { "data-ruflet-tabs" => nav_payload.empty? ? name : ruflet_json(nav_payload), "hidden" => true }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_copy_button(label, text:, toast: "Copied", haptic: true, **attrs) ⇒ Object
170 171 172 173 |
# File 'lib/ruflet/rails/view_helpers.rb', line 170 def (label, text:, toast: "Copied", haptic: true, **attrs) payload = ruflet_compact_hash(component: "clipboard", text: text, toast: toast, haptic: haptic) ruflet_action_tag("button", label, payload, { "type" => "button" }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_drawer(action: :root, payload: {}, **attrs, &block) ⇒ Object
A drawer the native shell hides and re-renders as a native
NavigationDrawer. Items are ruflet_drawer_item links.
<%= ruflet_drawer do %>
<%= ruflet_drawer_item "Home", root_path, icon: "home" %>
<%= ruflet_drawer_item "Settings", settings_path, icon: "settings", nav: :push %>
<% end %>
113 114 115 116 117 118 |
# File 'lib/ruflet/rails/view_helpers.rb', line 113 def ruflet_drawer(action: :root, payload: {}, **attrs, &block) ruflet_build_tag("nav", ruflet_capture(&block), { "data-ruflet-drawer" => ruflet_json(ruflet_compact_hash(ruflet_stringify_keys(payload).merge(action: action.to_s))), "hidden" => true }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_drawer_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_drawer.
121 122 123 124 125 126 127 128 129 130 |
# File 'lib/ruflet/rails/view_helpers.rb', line 121 def ruflet_drawer_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) item_payload = ruflet_stringify_keys(payload) data = { "href" => href, "data-ruflet-icon" => ruflet_json(ruflet_compact_hash(item_payload.merge(icon: icon, label: label, action: nav&.to_s))) } data["data-ruflet-selected"] = "true" if selected ruflet_build_tag("a", label, data.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_frame(path, height: 600, width: "100%", title: "Ruflet", style: nil, **attrs) ⇒ Object
Embed a mounted Ruflet route as an isolated, responsive frame.
path - the Ruflet mount route ("/products") or a full URL. height - CSS height; a number is treated as pixels (default 600). width - CSS width; a number is treated as pixels (default "100%"). title - iframe title for accessibility (default "Ruflet"). style - extra CSS appended to the frame's inline style. attrs - any other iframe attributes (underscores become dashes).
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ruflet/rails/view_helpers.rb', line 31 def ruflet_frame(path, height: 600, width: "100%", title: "Ruflet", style: nil, **attrs) base_style = "border:0;width:#{ruflet_css_dimension(width)};height:#{ruflet_css_dimension(height)};" attributes = { "src" => path.to_s, "title" => title.to_s, "loading" => "lazy", "style" => [base_style, style].compact.join(" ").strip } attrs.each { |key, value| attributes[key.to_s.tr("_", "-")] = value } markup = +"<iframe" attributes.each { |key, value| markup << %( #{key}="#{ERB::Util.html_escape(value)}") } markup << "></iframe>" ruflet_html_safe(markup) end |
#ruflet_haptic_button(label, style: "selection", **attrs) ⇒ Object
180 181 182 183 |
# File 'lib/ruflet/rails/view_helpers.rb', line 180 def (label, style: "selection", **attrs) payload = ruflet_compact_hash(component: "haptic", style: style) ruflet_action_tag("button", label, payload, { "type" => "button" }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_launch_link(label, href, mode: nil, **attrs) ⇒ Object
175 176 177 178 |
# File 'lib/ruflet/rails/view_helpers.rb', line 175 def ruflet_launch_link(label, href, mode: nil, **attrs) payload = ruflet_compact_hash(component: "url_launcher", url: href, mode: mode) ruflet_action_tag("a", label, payload, { "href" => href }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_nav_item(label, href, icon:, selected: false, color: nil, size: 24, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_bottom_nav.
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ruflet/rails/view_helpers.rb', line 95 def ruflet_nav_item(label, href, icon:, selected: false, color: nil, size: 24, payload: {}, **attrs) item_payload = ruflet_stringify_keys(payload) data = { "href" => href, "data-ruflet-icon" => ruflet_json(ruflet_compact_hash(item_payload.merge(icon: icon, label: label, color: color, size: size))) } data["data-ruflet-selected"] = "true" if selected ruflet_build_tag("a", label, data.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_navigation_rail(action: :root, extended: nil, label_type: nil, breakpoint: nil, payload: {}, **attrs, &block) ⇒ Object Also known as: ruflet_rail
Desktop/tablet navigation the native shell hides and re-renders as a native NavigationRail beside the WebView body.
<%= ruflet_navigation_rail extended: true do %>
<%= ruflet_rail_item "Home", root_path, icon: "home" %>
<%= ruflet_rail_item "Inbox", inbox_path, icon: "mail" %>
<% end %>
139 140 141 142 143 144 145 146 |
# File 'lib/ruflet/rails/view_helpers.rb', line 139 def (action: :root, extended: nil, label_type: nil, breakpoint: nil, payload: {}, **attrs, &block) payload = ruflet_compact_hash(ruflet_stringify_keys(payload).merge(action: action.to_s, extended: extended, label_type: label_type, breakpoint: breakpoint)) ruflet_build_tag("nav", ruflet_capture(&block), { "data-ruflet-rail" => ruflet_json(payload), "hidden" => true }.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_rail_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) ⇒ Object
A destination inside ruflet_navigation_rail.
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ruflet/rails/view_helpers.rb', line 151 def ruflet_rail_item(label, href, icon:, selected: false, nav: nil, payload: {}, **attrs) item_payload = ruflet_stringify_keys(payload) data = { "href" => href, "data-ruflet-icon" => ruflet_json(ruflet_compact_hash(item_payload.merge(icon: icon, label: label, action: nav&.to_s))) } data["data-ruflet-selected"] = "true" if selected ruflet_build_tag("a", label, data.merge(ruflet_dash_attrs(attrs))) end |
#ruflet_share_link(label, href = "#", text: nil, title: nil, subject: nil, url: nil, files: nil, **attrs) ⇒ Object
Native platform services from ERB. These are normal HTML elements in a browser and native service calls inside Ruflet::Rails.native_app.
164 165 166 167 168 |
# File 'lib/ruflet/rails/view_helpers.rb', line 164 def ruflet_share_link(label, href = "#", text: nil, title: nil, subject: nil, url: nil, files: nil, **attrs) payload = ruflet_compact_hash(component: "share", text: text, title: title, subject: subject, url: url || href, files: files) ruflet_action_tag("a", label, payload, { "href" => href }.merge(ruflet_dash_attrs(attrs))) end |