hotwire_native_rails 0.1.0 → 0.2.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 +4 -4
- data/README.md +23 -27
- data/lib/generators/hotwire_native/hotwire_native_generator.rb +86 -5
- data/lib/generators/hotwire_native/templates/controllers/concerns/device_format.rb +13 -0
- data/lib/generators/hotwire_native/templates/controllers/hotwire_native/v1/android/path_configuration_controller.rb +5 -0
- data/lib/generators/hotwire_native/templates/controllers/hotwire_native/v1/ios/path_configuration_controller.rb +5 -0
- data/lib/generators/hotwire_native/templates/helpers/hotwire_native_helper.rb +6 -0
- data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/button_controller.js +20 -0
- data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/form_controller.js +34 -0
- data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/menu_controller.js +47 -0
- data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/overflow_menu_controller.js +22 -0
- data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/review_prompt_controller.js +11 -0
- data/lib/generators/hotwire_native/templates/routes/hotwire_native.rb +10 -0
- data/lib/generators/hotwire_native/templates/test_unit/hotwire_native_helper_test.rb +1 -0
- data/lib/hotwire_native_rails/version.rb +1 -1
- metadata +10 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a4224784bdab848b3b193b9902b70940618a3d37aa48b9502f5e98756fe4d31
|
4
|
+
data.tar.gz: cf49ce2b8982ae85ac45032bf39f64b20971f6521e83e9080a417fb0269fd9da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92d384f1c486c93494a14e2635739a335e68a599201fcf3642ce1f19986d1d2b951fd7fbfb3a0e85bec69d0bddc45f6b34e0df5c23a7e6aae5c9f5f635c43755
|
7
|
+
data.tar.gz: 2bf89e359cd0e1518367f32ae7edd349e6aee123ccdd09b4cbb73335d8c113d6b230838f56bee15aee092b4de791615a113eaf90622214807b68a01c83138863
|
data/README.md
CHANGED
@@ -1,43 +1,39 @@
|
|
1
|
-
#
|
1
|
+
# Hotwire Native Rails generator
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/hotwire_native_rails`. To experiment with that code, run `bin/console` for an interactive prompt.
|
3
|
+
Power pack to make your Rails app [Hotwire Native](https://native.hotwired.dev)
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
Install the gem and add to the application's Gemfile by executing:
|
7
|
+
Install the gem:
|
12
8
|
|
13
|
-
```
|
14
|
-
bundle add
|
9
|
+
```sh
|
10
|
+
bundle add hotwire_native_rails
|
15
11
|
```
|
16
12
|
|
17
|
-
|
13
|
+
Run the generator:
|
18
14
|
|
19
|
-
```
|
20
|
-
|
15
|
+
```sh
|
16
|
+
rails g hotwire_native_rails
|
21
17
|
```
|
22
18
|
|
23
19
|
## Usage
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
-
|
33
|
-
## Contributing
|
34
|
-
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hotwire_native_rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/hotwire_native_rails/blob/master/CODE_OF_CONDUCT.md).
|
21
|
+
#### Helpers
|
22
|
+
- `viewport_meta_tag` - forbid zooming on mobile/native
|
23
|
+
- use `data: { turbo_action: replace_if_native }` to submit authentication forms & forms in modals
|
24
|
+
- `:mobile` request variant. `index.html+mobile.erb`
|
25
|
+
- override link_to to not open internal links in in-app browser on native app
|
36
26
|
|
37
|
-
|
27
|
+
#### CSS
|
28
|
+
- `turbo-native:` css variant (works with CSS and Tailwind)
|
38
29
|
|
39
|
-
|
30
|
+
#### Bridge Components
|
31
|
+
- install Hotwire Native Bridge (works with Importmaps and Node)
|
32
|
+
- add default bridge components (`Form`, `Menu`, `Button`)
|
33
|
+
- `bridge_form_with` - easily apply Bridge Form component
|
40
34
|
|
41
|
-
|
35
|
+
#### Path Configuration
|
36
|
+
- `path_configuration_controller` for `ios` and `android`
|
42
37
|
|
43
|
-
|
38
|
+
gem build hotwire_native_rails.gemspec
|
39
|
+
gem push hotwire_native_rails-0.1.0.gem
|
@@ -1,17 +1,98 @@
|
|
1
1
|
class HotwireNativeGenerator < Rails::Generators::Base
|
2
2
|
source_root File.expand_path("templates", __dir__)
|
3
3
|
|
4
|
+
def add_gems
|
5
|
+
gem "browser"
|
6
|
+
end
|
7
|
+
|
4
8
|
def copy_files
|
9
|
+
# helpers
|
5
10
|
copy_file "helpers/hotwire_native_helper.rb", "app/helpers/hotwire_native_helper.rb"
|
6
11
|
copy_file "test_unit/hotwire_native_helper_test.rb", "test/helpers/hotwire_native_helper_test.rb"
|
7
12
|
|
8
|
-
#
|
9
|
-
|
13
|
+
# routes
|
14
|
+
copy_file "routes/hotwire_native.rb", "config/routes/hotwire_native.rb"
|
15
|
+
copy_file "controllers/hotwire_native/v1/android/path_configuration_controller.rb", "app/controllers/hotwire_native/v1/android/path_configuration_controller.rb"
|
16
|
+
copy_file "controllers/hotwire_native/v1/ios/path_configuration_controller.rb", "app/controllers/hotwire_native/v1/ios/path_configuration_controller.rb"
|
17
|
+
|
18
|
+
# :native request variant
|
19
|
+
copy_file "controllers/concerns/device_format.rb", "app/controllers/concerns/device_format.rb"
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_detect_device_to_application_controller
|
23
|
+
inject_into_class "app/controllers/application_controller.rb", ApplicationController, " include DetectDevice\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_routes
|
27
|
+
route "draw(:hotwire_native)"
|
28
|
+
end
|
29
|
+
|
30
|
+
# https://native.hotwired.dev/reference/bridge-installation
|
31
|
+
def install_javascript
|
32
|
+
copy_file "javascript/controllers/bridge/button_controller.js", "app/javascript/controllers/bridge/button_controller.js"
|
33
|
+
copy_file "javascript/controllers/bridge/menu_controller.js", "app/javascript/controllers/bridge/menu_controller.js"
|
34
|
+
copy_file "javascript/controllers/bridge/form_controller.js", "app/javascript/controllers/bridge/form_controller.js"
|
35
|
+
copy_file "javascript/controllers/bridge/overflow_menu_controller.js", "app/javascript/controllers/bridge/overflow_menu_controller.js"
|
36
|
+
|
37
|
+
run "bin/importmap pin @hotwired/stimulus @hotwired/hotwire-native-bridge" if importmaps?
|
38
|
+
run "yarn add @hotwired/stimulus @hotwired/hotwire-native-bridge" if node?
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_viewport_meta_tag
|
42
|
+
gsub_file "app/views/layouts/application.html.erb", "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">", "<%= viewport_meta_tag %>"
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_css_variants
|
46
|
+
return add_tailwind_css_variants if tailwind?
|
47
|
+
|
48
|
+
add_turbo_native_css
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_platform_identifier
|
52
|
+
gsub_file "app/views/layouts/application.html.erb", "<html>", "<html <%= platform_identifier %>>"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def importmaps?
|
58
|
+
Rails.root.join("config/importmap.rb").exist?
|
59
|
+
end
|
60
|
+
|
61
|
+
def node?
|
62
|
+
Rails.root.join("package.json").exist?
|
63
|
+
end
|
64
|
+
|
65
|
+
def tailwind?
|
66
|
+
Rails.root.join("config/tailwind.config.js").exist?
|
67
|
+
end
|
68
|
+
|
69
|
+
# class="turbo-native:hidden"
|
70
|
+
# class="non-turbo-native:hidden"
|
71
|
+
def add_tailwind_css_variants
|
72
|
+
prepend_to_file "config/tailwind.config.js", "const plugin = require('tailwindcss/plugin')\n"
|
73
|
+
|
74
|
+
inject_into_file "config/tailwind.config.js", after: "plugins: [" do
|
75
|
+
<<-JS
|
76
|
+
|
77
|
+
plugin(function({ addVariant }) {
|
78
|
+
addVariant("turbo-native", "html[data-turbo-native] &"),
|
79
|
+
addVariant("non-turbo-native", "html:not([data-turbo-native]) &")
|
80
|
+
}),
|
81
|
+
JS
|
82
|
+
end
|
83
|
+
end
|
10
84
|
|
11
|
-
|
85
|
+
# class="turbo-native:hidden"
|
86
|
+
def add_turbo_native_css
|
87
|
+
gsub_file "app/views/layouts/application.html.erb", "<body>", "<body class=\"<%= \"turbo-native\" if turbo_native_app? %>\">"
|
12
88
|
|
13
|
-
|
89
|
+
append_to_file "app/assets/stylesheets/application.css" do
|
90
|
+
<<-CSS
|
14
91
|
|
15
|
-
|
92
|
+
body.turbo-native .turbo-native:hidden {
|
93
|
+
display: none;
|
94
|
+
}
|
95
|
+
CSS
|
96
|
+
end
|
16
97
|
end
|
17
98
|
end
|
@@ -1,27 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HotwireNativeHelper
|
4
|
+
# forbid zooming on mobile devices
|
4
5
|
def viewport_meta_tag
|
5
6
|
content = ['width=device-width,initial-scale=1']
|
6
7
|
content << 'maximum-scale=1, user-scalable=0' if turbo_native_app? || browser.device.mobile?
|
7
8
|
tag.meta(name: 'viewport', content: content.join(','))
|
8
9
|
end
|
9
10
|
|
11
|
+
# set on <html> tag
|
10
12
|
def platform_identifier
|
11
13
|
'data-turbo-native' if turbo_native_app?
|
12
14
|
end
|
13
15
|
|
16
|
+
# link_to 'Next', next_path, data: { turbo_action: replace_if_native }
|
17
|
+
# https://turbo.hotwired.dev/handbook/drive#application-visits
|
14
18
|
def replace_if_native
|
15
19
|
return 'replace' if turbo_native_app?
|
16
20
|
|
17
21
|
'advance'
|
18
22
|
end
|
19
23
|
|
24
|
+
# override link_to to not open internal links in in-app browser on native app
|
20
25
|
def link_to(name = nil, options = nil, html_options = {}, &block)
|
21
26
|
html_options[:target] = '' if turbo_native_app? && internal_url?(url_for(options))
|
22
27
|
super(name, options, html_options, &block)
|
23
28
|
end
|
24
29
|
|
30
|
+
# https://github.com/joemasilotti/daily-log/blob/main/rails/app/helpers/form_helper.rb
|
25
31
|
class BridgeFormBuilder < ActionView::Helpers::FormBuilder
|
26
32
|
def submit(value = nil, options = {})
|
27
33
|
options[:data] ||= {}
|
data/lib/generators/hotwire_native/templates/javascript/controllers/bridge/button_controller.js
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
2
|
+
// Source:
|
3
|
+
// https://native.hotwired.dev/ios/bridge-components
|
4
|
+
// Docs:
|
5
|
+
// https://blog.corsego.com/hotwire-native-bridge-button
|
6
|
+
export default class extends BridgeComponent {
|
7
|
+
static component = "button"
|
8
|
+
|
9
|
+
connect() {
|
10
|
+
super.connect()
|
11
|
+
|
12
|
+
const element = this.bridgeElement
|
13
|
+
const title = element.bridgeAttribute("title")
|
14
|
+
const image = element.bridgeAttribute("ios-image")
|
15
|
+
const side = element.bridgeAttribute("side") || "right"
|
16
|
+
this.send("connect", {title, image, side}, () => {
|
17
|
+
this.element.click()
|
18
|
+
})
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
2
|
+
import { BridgeElement } from "@hotwired/hotwire-native-bridge"
|
3
|
+
// Source:
|
4
|
+
// https://github.com/hotwired/hotwire-native-demo/blob/main/public/javascript/controllers/bridge/form_controller.js
|
5
|
+
// Docs:
|
6
|
+
// https://blog.corsego.com/hotwire-native-form-component
|
7
|
+
export default class extends BridgeComponent {
|
8
|
+
static component = "form"
|
9
|
+
static targets = [ "submit" ]
|
10
|
+
|
11
|
+
connect() {
|
12
|
+
super.connect()
|
13
|
+
this.notifyBridgeOfConnect()
|
14
|
+
}
|
15
|
+
|
16
|
+
notifyBridgeOfConnect() {
|
17
|
+
const submitButton = new BridgeElement(this.submitTarget)
|
18
|
+
const submitTitle = submitButton.title
|
19
|
+
|
20
|
+
this.send("connect", { submitTitle }, () => {
|
21
|
+
this.submitTarget.click()
|
22
|
+
})
|
23
|
+
}
|
24
|
+
|
25
|
+
submitStart(event) {
|
26
|
+
this.submitTarget.disabled = true
|
27
|
+
this.send("submitDisabled")
|
28
|
+
}
|
29
|
+
|
30
|
+
submitEnd(event) {
|
31
|
+
this.submitTarget.disabled = false
|
32
|
+
this.send("submitEnabled")
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
2
|
+
import { BridgeElement } from "@hotwired/hotwire-native-bridge"
|
3
|
+
// Source:
|
4
|
+
// https://github.com/hotwired/hotwire-native-demo/blob/main/public/javascript/controllers/bridge/menu_controller.js
|
5
|
+
// Docs:
|
6
|
+
// https://blog.corsego.com/hotwire-native-bridge-menu-component
|
7
|
+
export default class extends BridgeComponent {
|
8
|
+
static component = "menu"
|
9
|
+
static targets = [ "title", "item" ]
|
10
|
+
|
11
|
+
show(event) {
|
12
|
+
if (this.enabled) {
|
13
|
+
event.stopImmediatePropagation()
|
14
|
+
this.notifyBridgeToDisplayMenu(event)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
notifyBridgeToDisplayMenu(event) {
|
19
|
+
const title = new BridgeElement(this.titleTarget).title
|
20
|
+
const items = this.makeMenuItems(this.itemTargets)
|
21
|
+
|
22
|
+
this.send("display", { title, items }, message => {
|
23
|
+
const selectedIndex = message.data.selectedIndex
|
24
|
+
const selectedItem = new BridgeElement(this.itemTargets[selectedIndex])
|
25
|
+
|
26
|
+
selectedItem.click()
|
27
|
+
})
|
28
|
+
}
|
29
|
+
|
30
|
+
makeMenuItems(elements) {
|
31
|
+
const items = elements.map((element, index) => this.menuItem(element, index))
|
32
|
+
const enabledItems = items.filter(item => item)
|
33
|
+
|
34
|
+
return enabledItems
|
35
|
+
}
|
36
|
+
|
37
|
+
menuItem(element, index) {
|
38
|
+
const bridgeElement = new BridgeElement(element)
|
39
|
+
|
40
|
+
if (bridgeElement.disabled) return null
|
41
|
+
|
42
|
+
return {
|
43
|
+
title: bridgeElement.title,
|
44
|
+
index: index
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
2
|
+
// Source:
|
3
|
+
// https://github.com/hotwired/hotwire-native-demo/blob/main/public/javascript/controllers/bridge/overflow_menu_controller.js
|
4
|
+
// Docs:
|
5
|
+
// https://blog.corsego.com/hotwire-native-bridge-menu-component
|
6
|
+
|
7
|
+
export default class extends BridgeComponent {
|
8
|
+
static component = "overflow-menu"
|
9
|
+
|
10
|
+
connect() {
|
11
|
+
super.connect()
|
12
|
+
this.notifyBridgeOfConnect()
|
13
|
+
}
|
14
|
+
|
15
|
+
notifyBridgeOfConnect() {
|
16
|
+
const label = this.bridgeElement.title
|
17
|
+
|
18
|
+
this.send("connect", { label }, () => {
|
19
|
+
this.bridgeElement.click()
|
20
|
+
})
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
|
2
|
+
// Docs:
|
3
|
+
// https://blog.corsego.com/hotwire-native-leave-a-review-bridge-component
|
4
|
+
export default class extends BridgeComponent {
|
5
|
+
static component = "review-prompt"
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
super.connect()
|
9
|
+
this.send("connect")
|
10
|
+
}
|
11
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotwire_native_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaro Shm
|
@@ -28,7 +28,16 @@ files:
|
|
28
28
|
- Rakefile
|
29
29
|
- hotwire_native_rails.gemspec
|
30
30
|
- lib/generators/hotwire_native/hotwire_native_generator.rb
|
31
|
+
- lib/generators/hotwire_native/templates/controllers/concerns/device_format.rb
|
32
|
+
- lib/generators/hotwire_native/templates/controllers/hotwire_native/v1/android/path_configuration_controller.rb
|
33
|
+
- lib/generators/hotwire_native/templates/controllers/hotwire_native/v1/ios/path_configuration_controller.rb
|
31
34
|
- lib/generators/hotwire_native/templates/helpers/hotwire_native_helper.rb
|
35
|
+
- lib/generators/hotwire_native/templates/javascript/controllers/bridge/button_controller.js
|
36
|
+
- lib/generators/hotwire_native/templates/javascript/controllers/bridge/form_controller.js
|
37
|
+
- lib/generators/hotwire_native/templates/javascript/controllers/bridge/menu_controller.js
|
38
|
+
- lib/generators/hotwire_native/templates/javascript/controllers/bridge/overflow_menu_controller.js
|
39
|
+
- lib/generators/hotwire_native/templates/javascript/controllers/bridge/review_prompt_controller.js
|
40
|
+
- lib/generators/hotwire_native/templates/routes/hotwire_native.rb
|
32
41
|
- lib/generators/hotwire_native/templates/test_unit/hotwire_native_helper_test.rb
|
33
42
|
- lib/hotwire_native_rails.rb
|
34
43
|
- lib/hotwire_native_rails/version.rb
|