turbo-mount 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3f99f1305fc0312f04a390c3d7992e5dba4d8aba4bf14349a022cd2af528b5ff
4
+ data.tar.gz: b29a4f83ee2f6a3ef7b069908644273df3d07d656dee5b963cdc983c6aeebc39
5
+ SHA512:
6
+ metadata.gz: ef8a6e260eadec1dad5aa2aff35770d5713c80d31a6a84d0956b7af835cfa5eb994506173cc215dd04cde9da9f3a1a8db15320c95842d21f759eaf6e5453c2fc
7
+ data.tar.gz: 2d6975c85965b3772089a43e8a6a998537f2c2e15c3dcb41e69e00851fc069eadbac021b44eed119bc11644ffb290b0f26036f11658bb79473c10eedce058179
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog],
6
+ and this project adheres to [Semantic Versioning].
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2024-05-07
11
+
12
+ ### Added
13
+
14
+ - Initial implementation. ([@skryukov])
15
+
16
+ [@skryukov]: https://github.com/skryukov
17
+
18
+ [Unreleased]: https://github.com/skryukov/turbo-mount/compare/v0.1.0...HEAD
19
+ [0.1.0]: https://github.com/skryukov/turbo-mount/commits/v0.1.0
20
+
21
+ [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
22
+ [Semantic Versioning]: https://semver.org/spec/v2.0.0.html
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Svyatoslav Kryukov
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Turbo::Mount
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/turbo-mount.svg)](https://rubygems.org/gems/turbo-mount)
4
+
5
+ `Turbo::Mount` is a simple gem that allows you to add highly interactive components from React, Vue, Svelte, and other frameworks to your Hotwire application.
6
+
7
+ ## Installation
8
+
9
+ Install the gem and add to the application's Gemfile by executing:
10
+
11
+ $ bundle add turbo-mount
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ $ gem install turbo-mount
16
+
17
+ ## Usage
18
+
19
+ First, you need to initialize `TurboMount` and register the components you want to use:
20
+
21
+ ```js
22
+ import { Application } from "@hotwired/stimulus"
23
+ import { TurboMount } from "turbo-mount"
24
+
25
+ const application = Application.start()
26
+
27
+ // Initialize TurboMount and register the react stimulus controller
28
+ const turboMount = new TurboMount({application, framework: "react"});
29
+
30
+ // Register the components you want to use
31
+ import { SketchPicker } from 'react-color'
32
+ turboMount.register('SketchPicker', SketchPicker);
33
+ ```
34
+
35
+ Now you can use view helpers to mount the components:
36
+
37
+ ```erb
38
+ <%= turbo_mount_component("SketchPicker", framework: "react", props: {color: "#034"}) %>
39
+
40
+ <%# or using alias %>
41
+
42
+ <%= turbo_mount_react_component("SketchPicker", props: {color: "#430"}) %>
43
+ ```
44
+
45
+ In case you need to customize the component's behavior, or pass functions as props, you can create a custom controller:
46
+
47
+ ```js
48
+ // javascript/controllers/turbo_mount_react_sketch_picker_controller.js
49
+
50
+ import { TurboMountReactController } from "turbo-mount"
51
+
52
+ export default class extends TurboMountReactController {
53
+ get componentProps() {
54
+ return {
55
+ ...this.propsValue,
56
+ onChange: this.onChange,
57
+ };
58
+ }
59
+
60
+ onChange = (color) => {
61
+ this.propsValue = { ...this.propsValue, color: color.hex };
62
+ };
63
+ }
64
+ ```
65
+
66
+ ## Development
67
+
68
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
69
+
70
+ 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).
71
+
72
+ ## Contributing
73
+
74
+ Bug reports and pull requests are welcome on GitHub at https://github.com/skryukov/turbo-mount.
75
+
76
+ ## License
77
+
78
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,119 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { createElement } from 'react';
3
+ import { createRoot } from 'react-dom/client';
4
+ import { createApp } from 'vue';
5
+
6
+ class TurboMountController extends Controller {
7
+ connect() {
8
+ this._umountComponentCallback || (this._umountComponentCallback = this.mountComponent(this.mountElement, this.resolvedComponent, this.componentProps));
9
+ }
10
+ disconnect() {
11
+ this.umountComponent();
12
+ }
13
+ propsValueChanged() {
14
+ this.umountComponent();
15
+ this._umountComponentCallback = this.mountComponent(this.mountElement, this.resolvedComponent, this.componentProps);
16
+ }
17
+ get componentProps() {
18
+ return this.propsValue;
19
+ }
20
+ get mountElement() {
21
+ return this.element;
22
+ }
23
+ get resolvedComponent() {
24
+ return this.resolveComponent(this.componentValue);
25
+ }
26
+ umountComponent() {
27
+ this._umountComponentCallback && this._umountComponentCallback();
28
+ this._umountComponentCallback = undefined;
29
+ }
30
+ resolveComponent(component) {
31
+ const app = this.application;
32
+ return app.turboMount[this.framework].resolve(component);
33
+ }
34
+ }
35
+ TurboMountController.values = {
36
+ props: Object,
37
+ component: String
38
+ };
39
+
40
+ class TurboMountReactController extends TurboMountController {
41
+ constructor() {
42
+ super(...arguments);
43
+ this.framework = "react";
44
+ }
45
+ mountComponent(el, Component, props) {
46
+ const root = createRoot(el);
47
+ root.render(createElement(Component, props));
48
+ return root.unmount;
49
+ }
50
+ }
51
+
52
+ class TurboMountSvelteController extends TurboMountController {
53
+ constructor() {
54
+ super(...arguments);
55
+ this.framework = "svelte";
56
+ }
57
+ mountComponent(el, Component, props) {
58
+ const component = new Component({ target: el, props });
59
+ return component.$destroy;
60
+ }
61
+ }
62
+
63
+ class TurboMountVueController extends TurboMountController {
64
+ constructor() {
65
+ super(...arguments);
66
+ this.framework = "vue";
67
+ }
68
+ mountComponent(el, Component, props) {
69
+ const app = createApp(Component, props);
70
+ app.mount(el);
71
+ return app.unmount;
72
+ }
73
+ }
74
+
75
+ class TurboMount {
76
+ constructor(props) {
77
+ var _a;
78
+ this.components = new Map();
79
+ this.application = props.application;
80
+ this.framework = props.framework;
81
+ this.baseController = undefined;
82
+ if (!this.framework) {
83
+ throw new Error('framework is required');
84
+ }
85
+ (_a = this.application).turboMount || (_a.turboMount = {});
86
+ this.application.turboMount[this.framework] = this;
87
+ this.baseController = TurboMount.frameworkControllers.get(this.framework);
88
+ if (this.baseController) {
89
+ this.application.register(`turbo-mount-${this.framework}`, this.baseController);
90
+ }
91
+ }
92
+ register(name, component, controller) {
93
+ controller || (controller = this.baseController);
94
+ if (this.components.has(name)) {
95
+ throw new Error(`Component '${name}' is already registered.`);
96
+ }
97
+ this.components.set(name, component);
98
+ if (controller) {
99
+ const controllerName = `turbo-mount-${this.framework}-${this.camelToKebabCase(name)}`;
100
+ this.application.register(controllerName, controller);
101
+ }
102
+ }
103
+ resolve(name) {
104
+ const component = this.components.get(name);
105
+ if (!component) {
106
+ throw new Error(`Unknown component: ${name}`);
107
+ }
108
+ return component;
109
+ }
110
+ camelToKebabCase(str) {
111
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
112
+ }
113
+ }
114
+ TurboMount.frameworkControllers = new Map();
115
+ TurboMount.frameworkControllers.set("react", TurboMountReactController);
116
+ TurboMount.frameworkControllers.set("svelte", TurboMountSvelteController);
117
+ TurboMount.frameworkControllers.set("vue", TurboMountVueController);
118
+
119
+ export { TurboMount, TurboMountController, TurboMountReactController, TurboMountSvelteController, TurboMountVueController };
@@ -0,0 +1,2 @@
1
+ import{Controller as t}from"@hotwired/stimulus";import{createElement as o}from"react";import{createRoot as e}from"react-dom/client";import{createApp as r}from"vue";class n extends t{connect(){this._umountComponentCallback||(this._umountComponentCallback=this.mountComponent(this.mountElement,this.resolvedComponent,this.componentProps))}disconnect(){this.umountComponent()}propsValueChanged(){this.umountComponent(),this._umountComponentCallback=this.mountComponent(this.mountElement,this.resolvedComponent,this.componentProps)}get componentProps(){return this.propsValue}get mountElement(){return this.element}get resolvedComponent(){return this.resolveComponent(this.componentValue)}umountComponent(){this._umountComponentCallback&&this._umountComponentCallback(),this._umountComponentCallback=void 0}resolveComponent(t){return this.application.turboMount[this.framework].resolve(t)}}n.values={props:Object,component:String};class s extends n{constructor(){super(...arguments),this.framework="react"}mountComponent(t,r,n){const s=e(t);return s.render(o(r,n)),s.unmount}}class m extends n{constructor(){super(...arguments),this.framework="svelte"}mountComponent(t,o,e){return new o({target:t,props:e}).$destroy}}class i extends n{constructor(){super(...arguments),this.framework="vue"}mountComponent(t,o,e){const n=r(o,e);return n.mount(t),n.unmount}}class a{constructor(t){var o;if(this.components=new Map,this.application=t.application,this.framework=t.framework,this.baseController=void 0,!this.framework)throw new Error("framework is required");(o=this.application).turboMount||(o.turboMount={}),this.application.turboMount[this.framework]=this,this.baseController=a.frameworkControllers.get(this.framework),this.baseController&&this.application.register(`turbo-mount-${this.framework}`,this.baseController)}register(t,o,e){if(e||(e=this.baseController),this.components.has(t))throw new Error(`Component '${t}' is already registered.`);if(this.components.set(t,o),e){const o=`turbo-mount-${this.framework}-${this.camelToKebabCase(t)}`;this.application.register(o,e)}}resolve(t){const o=this.components.get(t);if(!o)throw new Error(`Unknown component: ${t}`);return o}camelToKebabCase(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}a.frameworkControllers=new Map,a.frameworkControllers.set("react",s),a.frameworkControllers.set("svelte",m),a.frameworkControllers.set("vue",i);export{a as TurboMount,n as TurboMountController,s as TurboMountReactController,m as TurboMountSvelteController,i as TurboMountVueController};
2
+ //# sourceMappingURL=turbo-mount.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turbo-mount.min.js","sources":["../src/controllers/turbo-mount-controller.ts","../src/controllers/turbo-mount-react-controller.ts","../src/turbo-mount.ts"],"sourcesContent":["import {Controller, ControllerConstructor} from \"@hotwired/stimulus\"\nimport {ApplicationWithTurboMount} from \"../turbo-mount\";\n\nexport abstract class TurboMountController<T> extends Controller {\n static values = {\n props: Object,\n component: String\n }\n declare readonly propsValue: object;\n declare readonly componentValue: string;\n\n abstract framework: string;\n\n abstract mountComponent(el: Element, component: string, props: object): () => void;\n\n umountComponentCallback?: () => void;\n\n connect() {\n this.umountComponentCallback ||= this.mountComponent(this.element, this.componentValue, this.propsValue);\n }\n\n disconnect() {\n this.umountComponent();\n }\n\n propsValueChanged() {\n this.umountComponent();\n this.umountComponentCallback = this.mountComponent(this.element, this.componentValue, this.componentProps);\n }\n\n get componentProps() {\n return this.propsValue;\n }\n\n umountComponent() {\n this.umountComponentCallback && this.umountComponentCallback();\n this.umountComponentCallback = undefined;\n }\n\n resolveComponent(component: string): T {\n const app = this.application as ApplicationWithTurboMount<T>\n return app.turboMount[this.framework].resolve(component);\n }\n\n static shouldRegister(controllerConstructor: ControllerConstructor, identifier: string, application: ApplicationWithTurboMount<any>) {\n const framework = identifier.split('-')[2];\n console.log({\n framework,\n identifier,\n modules: application.router.modules.map(m => m.identifier)\n })\n if (framework && identifier.startsWith(`turbo-mount-${framework}-`)\n && application.router.modules.find(m => m.identifier === identifier)) {\n console.log(controllerConstructor, application.turboMount[framework].baseController)\n return controllerConstructor !== application.turboMount[framework].baseController;\n }\n\n return true;\n }\n}\n\n\n","import {createElement, ComponentType} from \"react\";\nimport {createRoot} from \"react-dom/client\";\n\nimport {TurboMountController} from \"./turbo-mount-controller\";\n\nexport class TurboMountReactController extends TurboMountController<ComponentType> {\n framework = \"react\"\n\n mountComponent(el: Element, component: string, props: object) {\n const Component = this.resolveComponent(component);\n const root = createRoot(el);\n\n root.render(createElement(Component, props))\n\n return () => {\n root.unmount()\n }\n }\n}\n","import {Application, ControllerConstructor} from '@hotwired/stimulus';\nimport {TurboMountReactController} from \"./controllers\";\n\nexport interface ApplicationWithTurboMount<T> extends Application {\n turboMount: { [framework: string]: TurboMount<T> };\n}\n\nexport class TurboMount<T> {\n static frameworkControllers: Map<string, ControllerConstructor> = new Map();\n\n components: Map<string, T>;\n application: ApplicationWithTurboMount<T>;\n framework: string;\n baseController?: ControllerConstructor;\n\n constructor(props: { application: Application, framework: string }) {\n this.components = new Map();\n this.application = props.application as ApplicationWithTurboMount<T>;\n this.framework = props.framework;\n this.baseController = undefined;\n\n if (!this.framework) {\n throw new Error('framework is required');\n }\n\n this.application.turboMount ||= {};\n this.application.turboMount[this.framework] = this;\n\n this.baseController = TurboMount.frameworkControllers.get(this.framework);\n\n if (this.baseController) {\n this.application.register(`turbo-mount-${this.framework}`, this.baseController);\n }\n }\n\n camelToKebabCase(str: string) {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n }\n\n register(name: string, component: T) {\n if (this.components.has(name)) {\n throw new Error(`Component '${name}' is already registered.`);\n }\n this.components.set(name, component);\n\n if (this.baseController) {\n const controllerName = `turbo-mount-${this.framework}-${this.camelToKebabCase(name)}`;\n if (!this.application.router.modules.find(m => m.identifier === controllerName)) {\n this.application.register(controllerName, this.baseController);\n }\n }\n }\n\n resolve(name: string) {\n const component = this.components.get(name);\n if (!component) {\n throw new Error(`Unknown component: ${name}`);\n }\n return component;\n }\n}\n\nTurboMount.frameworkControllers.set(\"react\", TurboMountReactController)\n"],"names":["TurboMountController","Controller","connect","this","umountComponentCallback","mountComponent","element","componentValue","propsValue","disconnect","umountComponent","propsValueChanged","componentProps","undefined","resolveComponent","component","application","turboMount","framework","resolve","shouldRegister","controllerConstructor","identifier","split","console","log","modules","router","map","m","startsWith","find","baseController","values","props","Object","String","TurboMountReactController","constructor","el","Component","root","createRoot","render","createElement","unmount","TurboMount","components","Map","Error","_a","frameworkControllers","get","register","camelToKebabCase","str","replace","toLowerCase","name","has","set","controllerName"],"mappings":"oIAGM,MAAgBA,UAAgCC,EAclD,OAAAC,GACIC,KAAKC,0BAALD,KAAKC,wBAA4BD,KAAKE,eAAeF,KAAKG,QAASH,KAAKI,eAAgBJ,KAAKK,YAChG,CAED,UAAAC,GACIN,KAAKO,iBACR,CAED,iBAAAC,GACIR,KAAKO,kBACLP,KAAKC,wBAA0BD,KAAKE,eAAeF,KAAKG,QAASH,KAAKI,eAAgBJ,KAAKS,eAC9F,CAED,kBAAIA,GACA,OAAOT,KAAKK,UACf,CAED,eAAAE,GACIP,KAAKC,yBAA2BD,KAAKC,0BACrCD,KAAKC,6BAA0BS,CAClC,CAED,gBAAAC,CAAiBC,GAEb,OADYZ,KAAKa,YACNC,WAAWd,KAAKe,WAAWC,QAAQJ,EACjD,CAED,qBAAOK,CAAeC,EAA8CC,EAAoBN,GACpF,MAAME,EAAYI,EAAWC,MAAM,KAAK,GAMxC,OALAC,QAAQC,IAAI,CACRP,YACAI,aACAI,QAASV,EAAYW,OAAOD,QAAQE,KAAIC,GAAKA,EAAEP,iBAE/CJ,GAAaI,EAAWQ,WAAW,eAAeZ,OAC/CF,EAAYW,OAAOD,QAAQK,MAAKF,GAAKA,EAAEP,aAAeA,OACzDE,QAAQC,IAAIJ,EAAuBL,EAAYC,WAAWC,GAAWc,gBAC9DX,IAA0BL,EAAYC,WAAWC,GAAWc,eAI1E,EAtDMhC,EAAAiC,OAAS,CACZC,MAAOC,OACPpB,UAAWqB,QCDb,MAAOC,UAAkCrC,EAA/C,WAAAsC,uBACInC,KAASe,UAAG,OAYf,CAVG,cAAAb,CAAekC,EAAaxB,EAAmBmB,GAC3C,MAAMM,EAAYrC,KAAKW,iBAAiBC,GAClC0B,EAAOC,EAAWH,GAIxB,OAFAE,EAAKE,OAAOC,EAAcJ,EAAWN,IAE9B,KACHO,EAAKI,SAAS,CAErB,QCVQC,EAQT,WAAAR,CAAYJ,SAMR,GALA/B,KAAK4C,WAAa,IAAIC,IACtB7C,KAAKa,YAAckB,EAAMlB,YACzBb,KAAKe,UAAYgB,EAAMhB,UACvBf,KAAK6B,oBAAiBnB,GAEjBV,KAAKe,UACN,MAAM,IAAI+B,MAAM,0BAGpBC,EAAA/C,KAAKa,aAAYC,aAAAiC,EAAAjC,WAAe,CAAA,GAChCd,KAAKa,YAAYC,WAAWd,KAAKe,WAAaf,KAE9CA,KAAK6B,eAAiBc,EAAWK,qBAAqBC,IAAIjD,KAAKe,WAE3Df,KAAK6B,gBACL7B,KAAKa,YAAYqC,SAAS,eAAelD,KAAKe,YAAaf,KAAK6B,eAEvE,CAED,gBAAAsB,CAAiBC,GACb,OAAOA,EAAIC,QAAQ,kBAAmB,SAASC,aAClD,CAED,QAAAJ,CAASK,EAAc3C,GACnB,GAAIZ,KAAK4C,WAAWY,IAAID,GACpB,MAAM,IAAIT,MAAM,cAAcS,6BAIlC,GAFAvD,KAAK4C,WAAWa,IAAIF,EAAM3C,GAEtBZ,KAAK6B,eAAgB,CACrB,MAAM6B,EAAiB,eAAe1D,KAAKe,aAAaf,KAAKmD,iBAAiBI,KACzEvD,KAAKa,YAAYW,OAAOD,QAAQK,MAAKF,GAAKA,EAAEP,aAAeuC,KAC5D1D,KAAKa,YAAYqC,SAASQ,EAAgB1D,KAAK6B,eAEtD,CACJ,CAED,OAAAb,CAAQuC,GACJ,MAAM3C,EAAYZ,KAAK4C,WAAWK,IAAIM,GACtC,IAAK3C,EACD,MAAM,IAAIkC,MAAM,sBAAsBS,KAE1C,OAAO3C,CACV,EAnDM+B,EAAAK,qBAA2D,IAAIH,IAsD1EF,EAAWK,qBAAqBS,IAAI,QAASvB"}
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/engine"
4
+ require "turbo/mount/helpers"
5
+
6
+ module Turbo
7
+ module Mount
8
+ class Engine < Rails::Engine
9
+ # If you don't want to precompile assets (e.g., you're using jsbundling),
10
+ # you can do this in an initializer:
11
+ #
12
+ # config.after_initialize do
13
+ # config.assets.precompile -= Turbo::Mount::Engine::PRECOMPILE_ASSETS
14
+ # end
15
+ PRECOMPILE_ASSETS = %w[turbo-mount.js turbo-mount.min.js turbo-mount.min.js.map].freeze
16
+
17
+ initializer "turbo-mount.assets" do
18
+ if Rails.application.config.respond_to?(:assets)
19
+ Rails.application.config.assets.precompile += PRECOMPILE_ASSETS
20
+ end
21
+ end
22
+
23
+ initializer "turbo-mount.helpers" do
24
+ ActiveSupport.on_load(:action_controller_base) do
25
+ helper Turbo::Mount::Helpers
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Turbo
4
+ module Mount
5
+ module Helpers
6
+ def turbo_mount_component(component_name, framework:, props: {}, tag: "div", **attrs)
7
+ raise TypeError, "Component name expected" unless component_name.is_a? String
8
+
9
+ attrs["data-controller"] = "turbo-mount-#{framework}-#{component_name.underscore.dasherize}"
10
+ prefix = "data-#{attrs["data-controller"]}"
11
+ attrs["#{prefix}-component-value"] = component_name
12
+ attrs["#{prefix}-props-value"] = json_escape(props.to_json) if props.present?
13
+
14
+ content_tag(tag, nil, attrs)
15
+ end
16
+
17
+ def turbo_mount_react_component(component_name, **attrs)
18
+ turbo_mount_component(component_name, framework: "react", **attrs)
19
+ end
20
+
21
+ def turbo_mount_svelte_component(component_name, **attrs)
22
+ turbo_mount_component(component_name, framework: "svelte", **attrs)
23
+ end
24
+
25
+ def turbo_mount_vue_component(component_name, **attrs)
26
+ turbo_mount_component(component_name, framework: "vue", **attrs)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Turbo
4
+ module Mount
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "mount/version"
4
+ require_relative "mount/engine"
5
+
6
+ module Turbo
7
+ module Mount
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turbo-mount
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Svyatoslav Kryukov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ description: Add highly interactive components to your Hotwire application with Turbo
28
+ Mount.
29
+ email:
30
+ - me@skryukov.dev
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE.txt
37
+ - README.md
38
+ - app/assets/javascripts/turbo-mount.js
39
+ - app/assets/javascripts/turbo-mount.min.js
40
+ - app/assets/javascripts/turbo-mount.min.js.map
41
+ - lib/turbo/mount.rb
42
+ - lib/turbo/mount/engine.rb
43
+ - lib/turbo/mount/helpers.rb
44
+ - lib/turbo/mount/version.rb
45
+ homepage: https://github.com/skryukov/turbo-mount
46
+ licenses:
47
+ - MIT
48
+ metadata:
49
+ bug_tracker_uri: https://github.com/skryukov/turbo-mount/issues
50
+ changelog_uri: https://github.com/skryukov/turbo-mount/blob/main/CHANGELOG.md
51
+ documentation_uri: https://github.com/skryukov/turbo-mount/blob/main/README.md
52
+ homepage_uri: https://github.com/skryukov/turbo-mount
53
+ source_code_uri: https://github.com/skryukov/turbo-mount
54
+ rubygems_mfa_required: 'true'
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 3.0.0
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.5.7
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Use React, Vue, Svelte, and other components with Hotwire.
74
+ test_files: []