tombolo 0.9.0 → 0.9.1

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +114 -42
  3. data/lib/tombolo/version.rb +1 -1
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cacc9db2ac7d8ba235b9b142fcd8ff0b97bff68e85335c621ad305adb55839c
4
- data.tar.gz: 04f784cf784897a241fe0b410ab4856214c8ffe6879db882028deeec8adfe591
3
+ metadata.gz: c83c9dbdab6b8ff99150d3fa57531514628e2c4c98ed68f655cd4cc557553429
4
+ data.tar.gz: 18ce866491063647ae333e0f4cb6e768cef06c843139f97df077d4301aebd1d4
5
5
  SHA512:
6
- metadata.gz: 456ea07d98bb2e17a5e7dd33a926383ae84612faa4ec7d9874bb8b960d6ebfc2ece64b7c90ed82af38972a7fc45a874cbc08037e577e0cd9729f0d4268fe79fd
7
- data.tar.gz: de35b3d525d13de7535a7e57bd17312263157426ea119c3b96d1008e101c7e89cbf23cd904f21bbfd2416dd060424cb0dd92c868bcfa9a884c78a09276067420
6
+ metadata.gz: aff5dfca04cf8bd500be3cc099b36a7a85f4d65a4b138e99f7a44ec9feb47c02ee7e65bcae57ae458ab31884d0e6ffe06eed1d6787522b54eac9a7fd248ab940
7
+ data.tar.gz: 16d329db50843678dacc5d8b8d50a1c20d6c453b3dec5ca5a7b98cf1058c85d3a1c1f0987c179ed22edf3d85451d52f166c881e4116a886deab1dadfb89c570c
data/README.md CHANGED
@@ -1,12 +1,29 @@
1
1
  # Tombolo
2
2
 
3
- Minimal React component mounting for Rails, inspired by
4
- [react-rails](https://github.com/reactjs/react-rails).
5
-
6
- Tombolo is designed for modern Rails apps using jsbundling-rails and
7
- propshaft. It provides a `react_component` view helper and optional
8
- server-side rendering with no asset pipeline integration — just a component
9
- map and a few lines of JavaScript.
3
+ [![Gem Version](https://badge.fury.io/rb/tombolo.svg)](https://badge.fury.io/rb/tombolo)
4
+ [![npm](https://img.shields.io/npm/v/tombolo)](https://www.npmjs.com/package/tombolo)
5
+ [![CI](https://github.com/elektronaut/tombolo/actions/workflows/build.yml/badge.svg)](https://github.com/elektronaut/tombolo/actions/workflows/build.yml)
6
+ [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ Tombolo is a lightweight alternative to
9
+ [react-rails](https://github.com/reactjs/react-rails) for mounting React
10
+ [islands](https://www.patterns.dev/posts/islands-architecture) in your Rails
11
+ views. It provides a `react_component` view helper, client-side mounting via a
12
+ component map, and optional server-side rendering through ExecJS.
13
+
14
+ Built for React 18+, Tombolo targets modern Rails apps using
15
+ [jsbundling-rails](https://github.com/rails/jsbundling-rails) (or any JS
16
+ bundler) and [propshaft](https://github.com/rails/propshaft), with no asset
17
+ pipeline integration — just register your components and write a few lines of
18
+ JavaScript.
19
+
20
+ ## Compatibility
21
+
22
+ | Dependency | Versions |
23
+ |------------|----------|
24
+ | Ruby | >= 3.2 |
25
+ | Rails | >= 7.0 |
26
+ | React | 18, 19 |
10
27
 
11
28
  ## Installation
12
29
 
@@ -25,8 +42,9 @@ npm install tombolo
25
42
  pnpm add tombolo
26
43
  ```
27
44
 
28
- Run the install generator to create a config initializer and SSR entry
29
- point:
45
+ Optionally, run the install generator to create a config initializer
46
+ (`config/initializers/tombolo.rb`) and an SSR entry point
47
+ (`app/javascript/prerender.ts`):
30
48
 
31
49
  ```sh
32
50
  bin/rails generate tombolo:install
@@ -42,11 +60,14 @@ Render a React component from any view or partial:
42
60
  <%= react_component("Greeting", props: { name: "World" }) %>
43
61
  ```
44
62
 
63
+ This renders a `<div>` with `data-react-component` and `data-react-props`
64
+ attributes that the JavaScript side picks up.
65
+
45
66
  ### Client-side mounting
46
67
 
47
68
  Tombolo takes a component map — an object mapping component names to React
48
- components. The easiest way to create one is a barrel file that re-exports
49
- your components:
69
+ components. The easiest way to create one is a barrel file (a module that
70
+ re-exports from other modules):
50
71
 
51
72
  ```typescript
52
73
  // app/javascript/components/index.ts
@@ -54,36 +75,44 @@ export { Greeting } from "./Greeting";
54
75
  export { SearchForm } from "./SearchForm";
55
76
  ```
56
77
 
57
- Import it and call `Tombolo.start` to mount components on page load:
78
+ #### With Turbo
79
+
80
+ For apps using Turbo, use `Tombolo.mount` and `Tombolo.unmount` directly:
58
81
 
59
82
  ```typescript
60
83
  import * as Tombolo from "tombolo";
61
84
  import * as components from "./components";
62
85
 
63
- Tombolo.start(components);
86
+ document.addEventListener("turbo:load", () => Tombolo.mount(components));
87
+ document.addEventListener("turbo:before-cache", () => Tombolo.unmount());
64
88
  ```
65
89
 
66
- Both `Tombolo.mount` and `Tombolo.unmount` accept an optional `scope`
67
- parameter to limit operations to a subtree of the DOM:
90
+ #### Without Turbo
91
+
92
+ For apps without Turbo, `Tombolo.start` mounts components on
93
+ `DOMContentLoaded` (or immediately if the DOM is already loaded):
68
94
 
69
95
  ```typescript
70
- Tombolo.mount(components, document.getElementById("sidebar"));
96
+ import * as Tombolo from "tombolo";
97
+ import * as components from "./components";
98
+
99
+ Tombolo.start(components);
71
100
  ```
72
101
 
73
- #### Turbo
102
+ #### Scoped mounting
74
103
 
75
- For apps using Turbo, use `Tombolo.mount` and `Tombolo.unmount` directly:
104
+ Both `Tombolo.mount` and `Tombolo.unmount` accept an optional `scope`
105
+ parameter to limit operations to a subtree of the DOM:
76
106
 
77
107
  ```typescript
78
- import * as Tombolo from "tombolo";
79
- import * as components from "./components";
80
-
81
- document.addEventListener("turbo:load", () => Tombolo.mount(components));
82
- document.addEventListener("turbo:before-cache", () => Tombolo.unmount());
108
+ Tombolo.mount(components, document.getElementById("sidebar"));
83
109
  ```
84
110
 
85
111
  ### Server-side rendering
86
112
 
113
+ SSR is optional and requires the [execjs](https://github.com/rails/execjs)
114
+ gem.
115
+
87
116
  Create a server entry point that registers your components:
88
117
 
89
118
  ```typescript
@@ -94,8 +123,12 @@ import * as components from "./components";
94
123
  registerServerRenderer(components);
95
124
  ```
96
125
 
97
- Build it with esbuild (or your bundler of choice) targeting a CommonJS
98
- output that ExecJS can evaluate.
126
+ Build it with esbuild (or your bundler of choice) as a CommonJS bundle that
127
+ ExecJS can evaluate:
128
+
129
+ ```sh
130
+ esbuild app/javascript/prerender.ts --bundle --platform=neutral --outfile=app/assets/builds/prerender.js
131
+ ```
99
132
 
100
133
  Then use `prerender: true` in your views:
101
134
 
@@ -103,6 +136,10 @@ Then use `prerender: true` in your views:
103
136
  <%= react_component("Greeting", props: { name: "World" }, prerender: true) %>
104
137
  ```
105
138
 
139
+ When a component is prerendered, the server-rendered HTML is placed inside the
140
+ div and Tombolo uses `hydrateRoot` instead of `createRoot` on the client.
141
+ This preserves interactivity without a full re-render.
142
+
106
143
  The default server bundle path is `app/assets/builds/prerender.js`. To
107
144
  customize it, add an initializer:
108
145
 
@@ -113,29 +150,50 @@ Tombolo.configure do |config|
113
150
  end
114
151
  ```
115
152
 
116
- ## API Reference
153
+ ## Configuration
154
+
155
+ ```ruby
156
+ Tombolo.configure do |config|
157
+ # Convert snake_case prop keys to camelCase (default: false)
158
+ config.camelize_props = true
117
159
 
118
- ### npm
160
+ # Path to the server-side JS bundle for SSR
161
+ # (default: "app/assets/builds/prerender.js")
162
+ config.server_bundle = "app/assets/builds/prerender.js"
163
+ end
164
+ ```
119
165
 
120
- #### `Tombolo.start(components)`
166
+ `camelize_props` can also be overridden per-call:
121
167
 
122
- Calls `mount` on `DOMContentLoaded`, or immediately if the DOM is already
123
- loaded. Convenience function for apps without Turbo.
168
+ ```erb
169
+ <%= react_component("Greeting", props: { first_name: "World" }, camelize_props: true) %>
170
+ ```
171
+
172
+ ## API reference
173
+
174
+ ### JavaScript
124
175
 
125
- #### `Tombolo.mount(components, scope?)`
176
+ #### `mount(components, scope?)`
126
177
 
127
178
  Scans `scope` (default: `document`) for elements with a
128
- `data-react-component` attribute. For each element, looks up the component
129
- by name, parses props from `data-react-props`, and mounts it.
130
- Already-mounted elements are skipped. Missing components log a warning to
131
- the console.
179
+ `data-react-component` attribute. For each element, looks up the component by
180
+ name, parses props from `data-react-props`, and mounts it. Elements with a
181
+ `data-react-prerender` attribute are hydrated with `hydrateRoot`; all others
182
+ use `createRoot`. Already-mounted elements are skipped.
132
183
 
133
- #### `Tombolo.unmount(scope?)`
184
+ #### `unmount(scope?)`
134
185
 
135
186
  Unmounts all tracked React roots within `scope` (default: `document`).
136
187
 
188
+ #### `start(components)`
189
+
190
+ Calls `mount` on `DOMContentLoaded`, or immediately if the DOM is already
191
+ loaded.
192
+
137
193
  #### `registerServerRenderer(components)`
138
194
 
195
+ *Imported from `tombolo/server`.*
196
+
139
197
  Assigns a `renderComponent(name, propsJson)` function to `globalThis`,
140
198
  making it callable from ExecJS. Used in server entry points for SSR.
141
199
 
@@ -151,15 +209,12 @@ configuration.
151
209
 
152
210
  #### `Tombolo.configure { |config| ... }`
153
211
 
154
- - `config.camelize_props` — Convert snake_case prop keys to camelCase.
155
- Default: `false`
156
- - `config.server_bundle` — Path to the server-side JS bundle for SSR.
157
- Default: `"app/assets/builds/prerender.js"`
212
+ See [Configuration](#configuration) above.
158
213
 
159
214
  ## Migrating from react-rails
160
215
 
161
- The main difference is the helper signature. react-rails passes props as a
162
- positional argument, Tombolo uses a keyword argument:
216
+ **Helper signature.** react-rails passes props as a positional argument,
217
+ Tombolo uses a keyword argument:
163
218
 
164
219
  ```ruby
165
220
  # react-rails
@@ -169,6 +224,23 @@ react_component("Name", { title: "Hello" })
169
224
  react_component("Name", props: { title: "Hello" })
170
225
  ```
171
226
 
227
+ **No html_options argument.** react-rails accepts a third argument for HTML
228
+ attributes on the wrapper div. Tombolo does not support this — wrap the helper
229
+ call in your own tag if you need custom attributes.
230
+
231
+ **No asset pipeline integration.** Tombolo does not ship a component generator
232
+ or integrate with Sprockets/Webpacker. You manage your JavaScript build
233
+ yourself with jsbundling-rails or an equivalent.
234
+
235
+ **SSR setup.** Replace any `server_rendering.js` pack with a
236
+ `prerender.ts` entry point that calls `registerServerRenderer`. See
237
+ [Server-side rendering](#server-side-rendering) above.
238
+
239
+ ## Contributing
240
+
241
+ Bug reports and pull requests are welcome on
242
+ [GitHub](https://github.com/elektronaut/tombolo).
243
+
172
244
  ## License
173
245
 
174
246
  MIT
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tombolo
4
- VERSION = "0.9.0"
4
+ VERSION = "0.9.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tombolo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inge Jørgensen
@@ -23,8 +23,8 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '7.0'
26
- description: Drop-in replacement for react-rails with minimal footprint. Provides
27
- a view helper and optional SSR via ExecJS.
26
+ description: Lightweight alternative to react-rails for mounting React components
27
+ in Rails views with optional server-side rendering via ExecJS.
28
28
  email:
29
29
  - inge@elektronaut.no
30
30
  executables: []
@@ -64,5 +64,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  requirements: []
65
65
  rubygems_version: 4.0.3
66
66
  specification_version: 4
67
- summary: Minimal React component mounting for Rails
67
+ summary: Mount React components in Rails views with optional SSR
68
68
  test_files: []