react-components-rails 1.0.0.beta1 → 1.0.0.beta4
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/Gemfile.lock +2 -3
- data/README.md +8 -2
- data/lib/react-components-rails.rb +3 -0
- data/package.json +22 -21
- data/pnpm-lock.yaml +1064 -0
- data/react-components-rails.gemspec +3 -3
- data/src/index.ts +86 -38
- data/tsconfig.json +12 -8
- metadata +4 -17
- data/yarn.lock +0 -5101
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "react-components-rails"
|
8
8
|
spec.licenses = ["MIT"]
|
9
|
-
spec.version = "1.0.0.
|
9
|
+
spec.version = "1.0.0.beta4"
|
10
10
|
spec.authors = ["Renaud Chaput"]
|
11
11
|
spec.email = ["renchap@gmail.com"]
|
12
12
|
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.homepage = "https://github.com/renchap/webpacker-react"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
-
f.match(%r{^(test|spec|features)/})
|
18
|
+
f.match(%r{^(test|spec|features|pnpm-lock.yaml)/})
|
19
19
|
end
|
20
20
|
spec.bindir = "exe"
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.required_ruby_version = ">= 2.7.0"
|
25
25
|
|
26
26
|
spec.add_development_dependency "bundler", "~> 2.3"
|
27
|
-
spec.add_development_dependency "rake", "~>
|
27
|
+
# spec.add_development_dependency "rake", "~> 12.0"
|
28
28
|
# spec.add_development_dependency "minitest", "~> 5.0"
|
29
29
|
# spec.add_development_dependency "capybara"
|
30
30
|
# spec.add_development_dependency "selenium-webdriver"
|
data/src/index.ts
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
import React from "react"
|
2
2
|
import ReactDOM from "react-dom"
|
3
|
-
import
|
4
|
-
|
5
|
-
import assign from "lodash/assign"
|
6
|
-
import omit from "lodash/omit"
|
3
|
+
import type ReactDOMClient from "react-dom/client"
|
4
|
+
|
7
5
|
// import ujs from './ujs'
|
8
6
|
|
9
7
|
const CLASS_ATTRIBUTE_NAME = "data-react-class"
|
@@ -11,46 +9,79 @@ const PROPS_ATTRIBUTE_NAME = "data-react-props"
|
|
11
9
|
|
12
10
|
declare global {
|
13
11
|
interface Window {
|
14
|
-
ReactComponentsRails:
|
12
|
+
ReactComponentsRails: ReactComponentsRails
|
15
13
|
}
|
16
14
|
}
|
17
15
|
|
18
|
-
|
19
|
-
registeredComponents
|
16
|
+
class ReactComponentsRails {
|
17
|
+
#registeredComponents = {} as { [name: string]: React.ComponentType }
|
18
|
+
#mountedRoots = [] as ReactDOMClient.Root[]
|
19
|
+
#ReactDOMClient = undefined as typeof ReactDOMClient | undefined | false
|
20
|
+
|
21
|
+
static getInstance() {
|
22
|
+
if (typeof window.ReactComponentsRails === "undefined") {
|
23
|
+
const instance = new ReactComponentsRails()
|
24
|
+
window.ReactComponentsRails = instance
|
25
|
+
|
26
|
+
// ujs.setup(this.mountComponents.bind(this), this.unmountComponents.bind(this))
|
27
|
+
}
|
28
|
+
|
29
|
+
return window.ReactComponentsRails
|
30
|
+
}
|
20
31
|
|
21
|
-
render(node: Element, component: React.ComponentType) {
|
32
|
+
private render(node: Element, component: React.ComponentType) {
|
22
33
|
const propsJson = node.getAttribute(PROPS_ATTRIBUTE_NAME)
|
23
34
|
const props = propsJson && JSON.parse(propsJson)
|
24
35
|
|
25
36
|
const reactElement = React.createElement(component, props)
|
26
37
|
|
27
|
-
|
28
|
-
|
38
|
+
if (this.#ReactDOMClient) {
|
39
|
+
const root = this.#ReactDOMClient.createRoot(node)
|
40
|
+
root.render(reactElement)
|
41
|
+
this.#mountedRoots.push(root)
|
42
|
+
} else {
|
43
|
+
ReactDOM.render(reactElement, node)
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
private registerComponents(components: {
|
48
|
+
[name: string]: React.ComponentType
|
49
|
+
}) {
|
50
|
+
const alreadyExisting: string[] = []
|
29
51
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
52
|
+
Object.keys(components).forEach((key) => {
|
53
|
+
if (this.#registeredComponents[key]) alreadyExisting.push(key)
|
54
|
+
else {
|
55
|
+
const comp = components[key]
|
56
|
+
this.#registeredComponents[key] = comp
|
57
|
+
}
|
58
|
+
})
|
59
|
+
|
60
|
+
if (alreadyExisting.length > 0) {
|
36
61
|
console.error(
|
37
|
-
`react-components-rails: can not register components. Following components are already registered: ${
|
62
|
+
`react-components-rails: can not register components. Following components are already registered: ${alreadyExisting.join(
|
63
|
+
", "
|
64
|
+
)}`
|
38
65
|
)
|
39
66
|
}
|
40
67
|
|
41
|
-
assign(this.registeredComponents, omit(components, collisions))
|
42
68
|
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
|
-
},
|
69
|
+
}
|
51
70
|
|
52
|
-
|
53
|
-
|
71
|
+
// Not used for now, useful for UJS
|
72
|
+
// private unmountComponents() {
|
73
|
+
// if (this.#ReactDOMClient) {
|
74
|
+
// this.#mountedRoots.forEach((root) => root.unmount())
|
75
|
+
// this.#mountedRoots = []
|
76
|
+
// } else {
|
77
|
+
// const mounted = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
|
78
|
+
// for (let i = 0; i < mounted.length; i += 1) {
|
79
|
+
// ReactDOM.unmountComponentAtNode(mounted[i])
|
80
|
+
// }
|
81
|
+
// }
|
82
|
+
// }
|
83
|
+
|
84
|
+
private mountComponents() {
|
54
85
|
const toMount = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
|
55
86
|
|
56
87
|
for (let i = 0; i < toMount.length; i += 1) {
|
@@ -64,7 +95,7 @@ const ReactComponentsRails = {
|
|
64
95
|
continue
|
65
96
|
}
|
66
97
|
|
67
|
-
const component = registeredComponents[className]
|
98
|
+
const component = this.#registeredComponents[className]
|
68
99
|
|
69
100
|
if (component) {
|
70
101
|
if (node.innerHTML.length === 0) this.render(node, component)
|
@@ -74,17 +105,34 @@ const ReactComponentsRails = {
|
|
74
105
|
)
|
75
106
|
}
|
76
107
|
}
|
77
|
-
}
|
108
|
+
}
|
78
109
|
|
79
110
|
setup(components = {}) {
|
80
|
-
|
81
|
-
window.ReactComponentsRails
|
82
|
-
|
83
|
-
}
|
111
|
+
this.loadReactDOMClient().then(() => {
|
112
|
+
window.ReactComponentsRails.registerComponents(components)
|
113
|
+
window.ReactComponentsRails.mountComponents()
|
114
|
+
})
|
115
|
+
}
|
84
116
|
|
85
|
-
|
86
|
-
|
87
|
-
|
117
|
+
private loadReactDOMClient() {
|
118
|
+
return new Promise<void>((resolve) => {
|
119
|
+
if (this.#ReactDOMClient) resolve()
|
120
|
+
|
121
|
+
import("react-dom/client")
|
122
|
+
.then((i) => {
|
123
|
+
// with some bundlers, it can be imported as `.default`, while not with some others
|
124
|
+
this.#ReactDOMClient = i.default || i
|
125
|
+
resolve()
|
126
|
+
})
|
127
|
+
.catch(() => {
|
128
|
+
// if this fails, then we will fallback to the legacy API
|
129
|
+
this.#ReactDOMClient = false
|
130
|
+
resolve()
|
131
|
+
})
|
132
|
+
})
|
133
|
+
}
|
88
134
|
}
|
89
135
|
|
90
|
-
|
136
|
+
const instance = ReactComponentsRails.getInstance()
|
137
|
+
|
138
|
+
export default instance
|
data/tsconfig.json
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
{
|
2
|
+
"exclude": ["dist/**/*"],
|
2
3
|
"compilerOptions": {
|
3
4
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
4
5
|
|
@@ -11,8 +12,11 @@
|
|
11
12
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
12
13
|
|
13
14
|
/* Language and Environment */
|
14
|
-
"target": "es2016"
|
15
|
-
"lib": [
|
15
|
+
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
16
|
+
"lib": [
|
17
|
+
"DOM",
|
18
|
+
"ES2016"
|
19
|
+
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
|
16
20
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
17
21
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
18
22
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
@@ -24,8 +28,8 @@
|
|
24
28
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
25
29
|
|
26
30
|
/* Modules */
|
27
|
-
"module": "
|
28
|
-
|
31
|
+
"module": "CommonJS" /* Specify what module code is generated. */,
|
32
|
+
"rootDir": "./src" /* Specify the root folder within your source files. */,
|
29
33
|
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
30
34
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
31
35
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
@@ -69,12 +73,12 @@
|
|
69
73
|
/* Interop Constraints */
|
70
74
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
71
75
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
72
|
-
"esModuleInterop": true
|
76
|
+
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
|
73
77
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
74
|
-
"forceConsistentCasingInFileNames": true
|
78
|
+
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
75
79
|
|
76
80
|
/* Type Checking */
|
77
|
-
"strict": true
|
81
|
+
"strict": true /* Enable all strict type-checking options. */,
|
78
82
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
|
79
83
|
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
|
80
84
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
@@ -96,6 +100,6 @@
|
|
96
100
|
|
97
101
|
/* Completeness */
|
98
102
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
99
|
-
"skipLibCheck": true
|
103
|
+
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
100
104
|
}
|
101
105
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: react-components-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Renaud Chaput
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.3'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '13.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '13.0'
|
41
27
|
description:
|
42
28
|
email:
|
43
29
|
- renchap@gmail.com
|
@@ -56,12 +42,13 @@ files:
|
|
56
42
|
- lib/component.rb
|
57
43
|
- lib/helpers.rb
|
58
44
|
- lib/railtie.rb
|
45
|
+
- lib/react-components-rails.rb
|
59
46
|
- package.json
|
47
|
+
- pnpm-lock.yaml
|
60
48
|
- react-components-rails.gemspec
|
61
49
|
- src/index.ts
|
62
50
|
- src/ujs.ts
|
63
51
|
- tsconfig.json
|
64
|
-
- yarn.lock
|
65
52
|
homepage: https://github.com/renchap/webpacker-react
|
66
53
|
licenses:
|
67
54
|
- MIT
|