0.0
The project is in a healthy, maintained state
Add highly interactive components to your Hotwire application with Turbo Mount.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 6.0.0
 Project Readme

Turbo Mount

Gem Version

TurboMount is a simple library that allows you to add highly interactive components from React, Vue, Svelte, and other frameworks to your Hotwire application.

Table of Contents

  • Installation
    • Importmaps
  • Usage
    • Initialization
      • Standard Initialization
      • Simplified Initialization
      • Plugin-Specific Initialization
    • View Helpers
    • Supported Frameworks
    • Custom Controllers
    • Vite Integration
    • Mount Target
  • License
Built by Evil Martians

Installation

To install TurboMount, add the following line to your Gemfile:

gem "turbo-mount"

If your project utilizes build tools such as Vite, also install the turbo-mount package:

npm install turbo-mount
# or with yarn
yarn add turbo-mount

Importmaps

To use TurboMount with importmaps, you need to pin the necessary JavaScript files in your config/importmap.rb:

pin "turbo-mount", to: "turbo-mount.min.js"
pin "turbo-mount/react", to: "turbo-mount/react.min.js"

This ensures that turbo-mount and its plugins are available in your application.

Usage

Initialization

To begin using TurboMount, start by initializing the library and registering the components you intend to use. Below are the steps to set up TurboMount with different configurations.

Standard Initialization

Import the necessary modules and initialize TurboMount with your application and the desired plugin. Here's how to set it up with a React plugin:

import { Application } from "@hotwired/stimulus";
import { TurboMount } from "turbo-mount";
import plugin from "turbo-mount/react";
import { SketchPicker } from 'react-color';

const application = Application.start();
const turboMount = new TurboMount({ application, plugin });

turboMount.register('SketchPicker', SketchPicker);

Simplified Initialization

If you prefer not to specify the application explicitly, TurboMount can automatically detect or initialize it. This approach uses the window.Stimulus if available; otherwise, it initializes a new Stimulus application:

import { TurboMount } from "turbo-mount";
import plugin from "turbo-mount/react";
import { SketchPicker } from 'react-color';

const turboMount = new TurboMount({ plugin });

turboMount.register('SketchPicker', SketchPicker);

Plugin-Specific Initialization

For a more streamlined setup, you can directly import a specialized version of TurboMount:

import { TurboMountReact } from "turbo-mount/react";
import { SketchPicker } from 'react-color';

const turboMount = new TurboMountReact();

turboMount.register('SketchPicker', SketchPicker);

View Helpers

Use the following helpers to mount components in your views:

<%= turbo_mount_component("SketchPicker", framework: "react", props: {color: "#034"}) %>

<%# or using alias %>

<%= turbo_mount_react_component("SketchPicker", props: {color: "#430"}) %>

This will generate the following HTML:

<div data-controller="turbo-mount-react-sketch-picker"
     data-turbo-mount-react-sketch-picker-component-value="SketchPicker"
     data-turbo-mount-react-sketch-picker-props-value="{&quot;color&quot;:&quot;#034&quot;}">
</div>

Supported Frameworks

TurboMount supports the following frameworks:

  • React: "turbo-mount/react"
  • Vue: "turbo-mount/vue"
  • Svelte: "turbo-mount/svelte"

To add support for other frameworks, create a custom controller class extending TurboMountController and provide a plugin. See included plugins for examples.

Custom Controllers

To customize component behavior or pass functions as props, create a custom controller:

import { TurboMountReactController } from "turbo-mount";

export default class extends TurboMountReactController {
  get componentProps() {
    return {
      ...this.propsValue,
      onChange: this.onChange,
    };
  }

  onChange = (color) => {
    this.propsValue = { ...this.propsValue, color: color.hex };
  };
}

Then pass this controller to the register method:

import SketchController from "controllers/turbo_mount/sketch_picker_controller";

turboMount.register('SketchPicker', SketchPicker, SketchController);

Vite Integration

TurboMount includes a registerComponents function that automates the loading of components (requires the stimulus-vite-helpers package). It also accepts an optional controllers property to autoload customized controllers:

import { TurboMount } from "turbo-mount/react";
import { registerComponents } from "turbo-mount/vite";

const controllers = import.meta.glob("./**/*_controller.js", { eager: true });
const components = import.meta.glob("/components/**/*.jsx", { eager: true });

const turboMount = new TurboMount();
registerComponents({ turboMount, components, controllers });

The registerComponents helper searches for controllers in the following paths:

  • controllers/turbo-mount/${framework}/${controllerName}
  • controllers/turbo-mount/${framework}-${controllerName}
  • controllers/turbo-mount-${framework}-${controllerName}
  • controllers/turbo-mount/${controllerName}
  • controllers/turbo-mount-${controllerName}

Mount Target

To specify a non-root mount target, use the data-<%= controller_name %>-target="mount" attribute:

<%= turbo_mount_react_component("SketchPicker", props: {color: "#430"}) do |controller_name| %>
  <h3>Color picker</h3>
  <div data-<%= controller_name %>-target="mount"></div>
<% end %>

License

The gem is available as open source under the terms of the MIT License.