react-components-rails 1.0.0.beta1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7e8b48934b25fc73c93eadc46d1fb4386a9289f40d1441be9a4a3f3cdb1cfb5d
4
+ data.tar.gz: 284e9e9ec4e81e4659f2a34385b3e7ab0df67ef258b60359da0b1a01e88eea1c
5
+ SHA512:
6
+ metadata.gz: 422e20effaf3f3b830a7f68fb771e8b61a7f42450cc80a4d491533be07995be85c4f11e4c37fea7643aaea7da857136e6909d725a5bf53d4dfe308a5a8bc42a4
7
+ data.tar.gz: 2487723877f13ea41e3652fb38355935f237ea9b59f4285a7c8583485e1eb933e622c19b0a54863472a7bb39d704e2c015558539e4719f2a4c607071f9233269
@@ -0,0 +1,9 @@
1
+ Fixes # .
2
+
3
+ Changes:
4
+
5
+ Please ensure that:
6
+ - [ ] Changelog is updated if not a minor patch
7
+ - [ ] Ruby linting is ok: `rubocop` is all green
8
+ - [ ] Javascript linting is ok: `cd javascript/webpacker_react-npm-module/ && yarn lint` is all green
9
+ - [ ] [Tests](https://github.com/renchap/webpacker-react#testing) are all green
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ node_modules/
2
+ tmp/
3
+ pkg/
4
+ dist/
data/.rubocop.yml ADDED
@@ -0,0 +1,119 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
4
+ # to ignore them, so only the ones explicitly set in this file are enabled.
5
+ DisabledByDefault: true
6
+ Exclude:
7
+ - '**/node_modules/**/*'
8
+ - '**/vendor/**/*'
9
+
10
+ # Prefer &&/|| over and/or.
11
+ Style/AndOr:
12
+ Enabled: true
13
+
14
+ # Do not use braces for hash literals when they are the last argument of a
15
+ # method call.
16
+ Style/BracesAroundHashParameters:
17
+ Enabled: true
18
+
19
+ # Align `when` with `case`.
20
+ Layout/CaseIndentation:
21
+ Enabled: true
22
+
23
+ # Align comments with method definitions.
24
+ Layout/CommentIndentation:
25
+ Enabled: true
26
+
27
+ # No extra empty lines.
28
+ Layout/EmptyLines:
29
+ Enabled: true
30
+
31
+ # In a regular class definition, no empty lines around the body.
32
+ Layout/EmptyLinesAroundClassBody:
33
+ Enabled: true
34
+
35
+ # In a regular module definition, no empty lines around the body.
36
+ Layout/EmptyLinesAroundModuleBody:
37
+ Enabled: true
38
+
39
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
40
+ Style/HashSyntax:
41
+ Enabled: true
42
+
43
+ # Method definitions after `private` or `protected` isolated calls need one
44
+ # extra level of indentation.
45
+ Layout/IndentationConsistency:
46
+ Enabled: true
47
+ EnforcedStyle: indented_internal_methods
48
+
49
+ # Two spaces, no tabs (for indentation).
50
+ Layout/IndentationWidth:
51
+ Enabled: true
52
+
53
+ Layout/SpaceAfterColon:
54
+ Enabled: true
55
+
56
+ Layout/SpaceAfterComma:
57
+ Enabled: true
58
+
59
+ Layout/SpaceAroundEqualsInParameterDefault:
60
+ Enabled: true
61
+
62
+ Layout/SpaceAroundKeyword:
63
+ Enabled: true
64
+
65
+ Layout/SpaceAroundOperators:
66
+ Enabled: true
67
+
68
+ Layout/SpaceBeforeFirstArg:
69
+ Enabled: true
70
+
71
+ # Defining a method with parameters needs parentheses.
72
+ Style/MethodDefParentheses:
73
+ Enabled: true
74
+
75
+ # Use `foo {}` not `foo{}`.
76
+ Layout/SpaceBeforeBlockBraces:
77
+ Enabled: true
78
+
79
+ # Use `foo { bar }` not `foo {bar}`.
80
+ Layout/SpaceInsideBlockBraces:
81
+ Enabled: true
82
+
83
+ # Use `{ a: 1 }` not `{a:1}`.
84
+ Layout/SpaceInsideHashLiteralBraces:
85
+ Enabled: true
86
+
87
+ Layout/SpaceInsideParens:
88
+ Enabled: true
89
+
90
+ # Check quotes usage according to lint rule below.
91
+ Style/StringLiterals:
92
+ Enabled: true
93
+ EnforcedStyle: double_quotes
94
+
95
+ # Detect hard tabs, no hard tabs.
96
+ Layout/Tab:
97
+ Enabled: true
98
+
99
+ # Blank lines should not have any spaces.
100
+ Layout/TrailingBlankLines:
101
+ Enabled: true
102
+
103
+ # No trailing whitespace.
104
+ Layout/TrailingWhitespace:
105
+ Enabled: true
106
+
107
+ # Use quotes for string literals when they are enough.
108
+ Style/UnneededPercentQ:
109
+ Enabled: true
110
+
111
+ # Align `end` with the matching keyword or starting expression except for
112
+ # assignments, where it should be aligned with the LHS.
113
+ Lint/EndAlignment:
114
+ Enabled: true
115
+ EnforcedStyleAlignWith: variable
116
+
117
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
118
+ Lint/RequireParentheses:
119
+ Enabled: true
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project maintainer at renchap@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rubocop", require: false
6
+
7
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ react-components-rails (1.0.0.beta1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ parallel (1.21.0)
11
+ parser (3.1.1.0)
12
+ ast (~> 2.4.1)
13
+ rainbow (3.1.1)
14
+ rake (13.0.6)
15
+ regexp_parser (2.2.1)
16
+ rexml (3.2.5)
17
+ rubocop (1.25.1)
18
+ parallel (~> 1.10)
19
+ parser (>= 3.1.0.0)
20
+ rainbow (>= 2.2.2, < 4.0)
21
+ regexp_parser (>= 1.8, < 3.0)
22
+ rexml
23
+ rubocop-ast (>= 1.15.1, < 2.0)
24
+ ruby-progressbar (~> 1.7)
25
+ unicode-display_width (>= 1.4.0, < 3.0)
26
+ rubocop-ast (1.16.0)
27
+ parser (>= 3.1.1.0)
28
+ ruby-progressbar (1.11.0)
29
+ unicode-display_width (2.1.0)
30
+
31
+ PLATFORMS
32
+ x86_64-darwin-21
33
+
34
+ DEPENDENCIES
35
+ bundler (~> 2.3)
36
+ rake (~> 13.0)
37
+ react-components-rails!
38
+ rubocop
39
+
40
+ BUNDLED WITH
41
+ 2.3.7
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Renaud Chaput
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # React-Components-Rails
2
+
3
+ _**Note:** This project was formerly known as `webpacker-rails`. Following Webpacker's deprecation, it has been renamed and rewritten to no longer rely on Webpacker. Documentation for the latest `webpacker-rails` release (1.0.0-beta.1) is [available here](https://github.com/renchap/webpacker-react/tree/v1.0.0-beta.1)._
4
+
5
+ React-Components-Rails makes it easy to use [React](https://reactjs.org/) with your Rails applications. It provides Controller and View helpers to render React Components on your application, and does not case about the way you ship your Javascript
6
+
7
+ ## Installation
8
+
9
+ First, you need to add this gem to your Rails app Gemfile:
10
+
11
+ ```ruby
12
+ gem 'react-components-rails', "~> 1.0.0.beta.1"
13
+ ```
14
+
15
+ Once done, run `bundle` to install the gem.
16
+
17
+ Then you need to update your `package.json` file to include the `react-components-rails` Javascript module:
18
+
19
+ `yarn add react-components-rails`
20
+
21
+ You are now all set!
22
+
23
+ ### Note about versions
24
+
25
+ React-Components-Rails contains two parts: a Javascript module and a Ruby gem. Both of those components respect [semantic versioning](http://semver.org). **When upgrading the gem, you need to upgrade the NPM module to the same minor version**. New patch versions can be released for each of the two independently, so it is ok to have the NPM module at version `A.X.Y` and the gem at version `A.X.Z`, but you should never have a different `A` or `X`.
26
+
27
+ ## Usage
28
+
29
+ The first step is to register your root components (those you want to load from your HTML).
30
+ In your app entry file, import your components as well as `react-components-rails` and register them. Considering you have a component in `app/javascript/components/hello.js`:
31
+
32
+ ```javascript
33
+ import Hello from "components/hello"
34
+ import ReactComponentsRails from "react-components-rails"
35
+
36
+ ReactComponentsRails.setup({ Hello }) // ES6 shorthand for {Hello: Hello}
37
+ ```
38
+
39
+ ### Rendering from a view
40
+
41
+ Use the `react_component` helper. The first argument is your component's name, the second one is the `props`:
42
+
43
+ ```erb
44
+ <%= react_component('Hello', name: 'React') %>
45
+ ```
46
+
47
+ You can pass a `tag` argument to render the React component in another tag than the default `div`. All other arguments will be passed to `content_tag`:
48
+
49
+ ```erb
50
+ <%= react_component('Hello', { name: 'React' }, tag: :span, class: 'my-custom-component') %>
51
+ # This will render <span class="my-custom-component" data-react-class="Hello" data-react-props="..."></span>
52
+ ```
53
+
54
+ ### Rendering from a controller
55
+
56
+ ```rb
57
+ class PageController < ApplicationController
58
+ def main
59
+ render react_component: 'Hello', props: { name: 'React' }
60
+ end
61
+ end
62
+ ```
63
+
64
+ You can use the `tag_options` argument to change the generated HTML, similar to the `react_component` method above:
65
+
66
+ ```rb
67
+ render react_component: 'Hello', props: { name: 'React' }, tag_options: { tag: :span, class: 'my-custom-component' }
68
+ ```
69
+
70
+ You can also pass any of the usual arguments to `render` in this call: `layout`, `status`, `content_type`, etc.
71
+
72
+ ### Hot Module Replacement
73
+
74
+ It should be supported out of the box, if supported by your Javascript stack. Please refer to your Javascript compiler/bundler documentation to do so.
75
+
76
+ <!--
77
+ ## Development
78
+
79
+ To work on this gem locally, you first need to clone and setup [the example application](https://github.com/renchap/webpacker-react-example).
80
+
81
+ Then you need to change the example app Gemfile to point to your local repository and run bundle afterwise:
82
+
83
+ ```ruby
84
+ gem 'webpacker-react', path: '~/code/webpacker-react/'
85
+ ```
86
+
87
+ Finally, you need to tell Yarn to use your local copy of the NPM module in this application, using [`yarn link`](https://yarnpkg.com/en/docs/cli/link):
88
+
89
+ ```
90
+ $ cd ~/code/webpacker-react/javascript/webpacker_react-npm-module/
91
+ $ yarn
92
+ $ cd dist/
93
+ $ yarn # compiles the code from src/ to dist/
94
+ $ yarn link
95
+ success Registered "webpacker-react".
96
+ info You can now run `yarn link "webpacker-react"` in the projects where you want to use this module and it will be used instead.
97
+ $ cd ~/code/webpacker-react-example/
98
+ $ yarn link webpacker-react
99
+ success Registered "webpacker-react".
100
+ ```
101
+
102
+ After launching `./bin/webpack-watcher` and `./bin/rails server` in your example app directory, you can now change the Ruby or Javascript code in your local `webpacker-react` repository, and test it immediately using the example app.
103
+
104
+ ## Testing
105
+
106
+ If you changed the local javascript package, first ensure it is build (see above).
107
+
108
+ To run the test suite:
109
+
110
+ ```sh
111
+ $ rake test
112
+ ```
113
+
114
+ If you change the javascript code, please ensure there are no style errors before committing:
115
+
116
+ ```sh
117
+ $ cd javascript/webpacker_react-npm-module/
118
+ $ yarn lint
119
+ ``` -->
120
+
121
+ ## Contributing
122
+
123
+ Bug reports and pull requests are welcome on GitHub at https://github.com/renchap/webpacker-react.
124
+ Please feel free to open issues about your needs and features you would like to be added.
125
+
126
+ ### Thanks
127
+
128
+ This gem has been inspired by the awesome work on [react-rails](https://github.com/reactjs/react-rails) and [react_on_rails](https://github.com/shakacode/react_on_rails/). Many thanks to their authors!
data/lib/component.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactComponentsRails
4
+ class Component
5
+ include ActionView::Helpers::TagHelper
6
+ include ActionView::Helpers::TextHelper
7
+
8
+ attr_accessor :name
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def render(props = {}, options = {})
15
+ tag = options.delete(:tag) || :div
16
+ data = { data: { "react-class" => @name, "react-props" => props.to_json } }
17
+
18
+ content_tag(tag, nil, options.deep_merge(data))
19
+ end
20
+ end
21
+ end
data/lib/helpers.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactComponentsRails
4
+ module Helpers
5
+ def react_component(component_name, props = {}, options = {})
6
+ ReactComponentsRails::Component.new(component_name).render(props, options)
7
+ end
8
+ end
9
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/railtie"
4
+
5
+ module ReactComponentsRails
6
+ class Engine < ::Rails::Engine
7
+ initializer :react_components do
8
+ ActiveSupport.on_load(:action_controller) do
9
+ ActionController::Base.helper ::ReactComponentsRails::Helpers
10
+ end
11
+
12
+ ActiveSupport.on_load :action_view do
13
+ include ::ReactComponentsRails::Helpers
14
+ end
15
+ end
16
+
17
+ initializer :react_components_rails_renderer, group: :all do |_app|
18
+ ActionController::Renderers.add :react_component do |component_name, options|
19
+ props = options.fetch(:props, {})
20
+ tag_options = options.fetch(:tag_options, {})
21
+ html = ReactComponentsRails::Component.new(component_name).render(props, tag_options)
22
+ render_options = options.merge(inline: html)
23
+ render(render_options)
24
+ end
25
+ end
26
+ end
27
+ end
data/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "react-components-rails",
3
+ "version": "1.0.0-beta.1",
4
+ "homepage": "https://github.com/renchap/react-components-rails",
5
+ "repository": "renchap/react-components-rails",
6
+ "author": {
7
+ "name": "Renaud Chaput",
8
+ "email": "renchap@gmail.com"
9
+ },
10
+ "license": "MIT",
11
+ "type": "module",
12
+ "source": "src/index.ts",
13
+ "exports": {
14
+ "require": "./dist/react-components-rails.cjs",
15
+ "default": "./dist/react-components-rails.modern.js"
16
+ },
17
+ "main": "./dist/react-components-rails.cjs",
18
+ "module": "./dist/react-components-rails.module.js",
19
+ "unpkg": "./dist/react-components-rails.umd.js",
20
+ "scripts": {
21
+ "build": "microbundle",
22
+ "dev": "microbundle watch"
23
+ },
24
+ "dependencies": {
25
+ "@types/lodash": "^4.14.179",
26
+ "lodash": "^4.17.21"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">= 0.14",
30
+ "react-dom": ">= 0.14"
31
+ },
32
+ "devDependencies": {
33
+ "@types/react": "^17.0.39",
34
+ "@types/react-dom": "^17.0.11",
35
+ "microbundle": "^0.14.2",
36
+ "prettier": "^2.5.1",
37
+ "react": "^17.0.2",
38
+ "react-dom": "^17.0.2",
39
+ "typescript": "^4.5.5"
40
+ },
41
+ "packageManager": "yarn@3.2.0",
42
+ "prettier": {
43
+ "semi": false
44
+ }
45
+ }
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "react-components-rails"
8
+ spec.licenses = ["MIT"]
9
+ spec.version = "1.0.0.beta1"
10
+ spec.authors = ["Renaud Chaput"]
11
+ spec.email = ["renchap@gmail.com"]
12
+
13
+ spec.summary = "Provides Rails helpers to render React Components"
14
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
15
+ spec.homepage = "https://github.com/renchap/webpacker-react"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.required_ruby_version = ">= 2.7.0"
25
+
26
+ spec.add_development_dependency "bundler", "~> 2.3"
27
+ spec.add_development_dependency "rake", "~> 13.0"
28
+ # spec.add_development_dependency "minitest", "~> 5.0"
29
+ # spec.add_development_dependency "capybara"
30
+ # spec.add_development_dependency "selenium-webdriver"
31
+ end
data/src/index.ts ADDED
@@ -0,0 +1,90 @@
1
+ import React from "react"
2
+ import ReactDOM from "react-dom"
3
+ import intersection from "lodash/intersection"
4
+ import keys from "lodash/keys"
5
+ import assign from "lodash/assign"
6
+ import omit from "lodash/omit"
7
+ // import ujs from './ujs'
8
+
9
+ const CLASS_ATTRIBUTE_NAME = "data-react-class"
10
+ const PROPS_ATTRIBUTE_NAME = "data-react-props"
11
+
12
+ declare global {
13
+ interface Window {
14
+ ReactComponentsRails: typeof ReactComponentsRails
15
+ }
16
+ }
17
+
18
+ const ReactComponentsRails = {
19
+ registeredComponents: {} as { [name: string]: React.ComponentType },
20
+
21
+ render(node: Element, component: React.ComponentType) {
22
+ const propsJson = node.getAttribute(PROPS_ATTRIBUTE_NAME)
23
+ const props = propsJson && JSON.parse(propsJson)
24
+
25
+ const reactElement = React.createElement(component, props)
26
+
27
+ ReactDOM.render(reactElement, node)
28
+ },
29
+
30
+ registerComponents(components: { [name: string]: React.Component }) {
31
+ const collisions = intersection(
32
+ keys(this.registeredComponents),
33
+ keys(components)
34
+ )
35
+ if (collisions.length > 0) {
36
+ console.error(
37
+ `react-components-rails: can not register components. Following components are already registered: ${collisions}`
38
+ )
39
+ }
40
+
41
+ assign(this.registeredComponents, omit(components, collisions))
42
+ return true
43
+ },
44
+
45
+ unmountComponents() {
46
+ const mounted = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
47
+ for (let i = 0; i < mounted.length; i += 1) {
48
+ ReactDOM.unmountComponentAtNode(mounted[i])
49
+ }
50
+ },
51
+
52
+ mountComponents() {
53
+ const { registeredComponents } = this
54
+ const toMount = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
55
+
56
+ for (let i = 0; i < toMount.length; i += 1) {
57
+ const node = toMount[i]
58
+ const className = node.getAttribute(CLASS_ATTRIBUTE_NAME)
59
+
60
+ if (!className) {
61
+ console.error(
62
+ `react-components-rails: no ${CLASS_ATTRIBUTE_NAME} attribute on element: ${node}`
63
+ )
64
+ continue
65
+ }
66
+
67
+ const component = registeredComponents[className]
68
+
69
+ if (component) {
70
+ if (node.innerHTML.length === 0) this.render(node, component)
71
+ } else {
72
+ console.error(
73
+ `react-components-rails: can not render a component that has not been registered: ${className}`
74
+ )
75
+ }
76
+ }
77
+ },
78
+
79
+ setup(components = {}) {
80
+ if (typeof window.ReactComponentsRails === "undefined") {
81
+ window.ReactComponentsRails = this
82
+ // ujs.setup(this.mountComponents.bind(this), this.unmountComponents.bind(this))
83
+ }
84
+
85
+ window.ReactComponentsRails.registerComponents(components)
86
+ window.ReactComponentsRails.mountComponents()
87
+ },
88
+ }
89
+
90
+ export default ReactComponentsRails