stimulus-rails 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af74b14f711ea67c26426322da6d6ae36c41db6757a56ae254bad08ccfc2a6b8
4
- data.tar.gz: 2bdbda7a1fd90f0cd964831f88cef4f269c92b560815012eb9875f12b0a0e406
3
+ metadata.gz: 664260a2f344790d144309fde0bcec8ced34dd3efd7ee4d64a1615e264bb2402
4
+ data.tar.gz: 02f64ba22c5783d1003d5cf47b8d307a88633544a1d90fb1ab4bf38382f58952
5
5
  SHA512:
6
- metadata.gz: 56334a9ca151712aec54fb89f8459ade60ae68dee9646e9234ed6b50da3c662d11d0bb890329e27f6ded8d8e1ddc9467cae94447d3f46173a568c0f6ddb7381d
7
- data.tar.gz: f3981eec7f58455483f9f0049b6e1680ff2b808d538d220e872284a2068adb5af70289c1430d89a08042577716527c1e440c20bc0a50a30d6a34b873f51d45c9
6
+ metadata.gz: a887a7a83ea54b73f92956ccdfa5e1d2e0410547505fd9eb70011db6989cfb82ba796e9dc44d73f764023dfab2e133a10cb8a4192126a2856a0b4e4e424c9edd
7
+ data.tar.gz: 3e4cdc03165d6c021deedaedbb3bbfe5205e7126a021c169bc32e9724a5ede72a8d36fc407a81585291f46110760208e244441dcca8f0c07531ab365dd889981
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Stimulus](https://stimulus.hotwired.dev) is a JavaScript framework with modest ambitions. It doesn’t seek to take over your entire front-end in fact, it’s not concerned with rendering HTML at all. Instead, it’s designed to augment your HTML with just enough behavior to make it shine. Stimulus pairs beautifully with Turbo to provide a complete solution for fast, compelling applications with a minimal amount of effort. Together they form the core of [Hotwire](https://hotwired.dev).
4
4
 
5
- Stimulus for Rails makes it easy to use this modest framework with the asset pipeline and ES6/ESM in the browser. It relies on either `importmap-rails` to make Stimulus available via ESM or a node-capable Rails (like via `jsbundling-rails`) to include Stimulus in the bundle. Make sure to install one of these first!
5
+ Stimulus for Rails makes it easy to use this modest framework with both import-mapped and JavaScript-bundled apps. It relies on either `importmap-rails` to make Stimulus available via ESM or a Node-capable Rails (like via `jsbundling-rails`) to include Stimulus in the bundle. Make sure to install one of these first!
6
6
 
7
7
 
8
8
  ## Installation
@@ -11,14 +11,25 @@ Stimulus for Rails makes it easy to use this modest framework with the asset pip
11
11
  2. Run `./bin/bundle install`.
12
12
  3. Run `./bin/rails stimulus:install`
13
13
 
14
- The installer will automatically detect whether you're using an [import map](https://github.com/rails/importmap-rails) or [JavaScript bundler](https://github.com/rails/jsbundling-rails) to manage your application's JavaScript. If you're using an import map, the Stimulus dependencies will be pinned to the versions of the library included with this gem. If you're using node, yarn will add the dependencies to your `package.json` file.
14
+ The installer will automatically detect whether you're using an [import map](https://github.com/rails/importmap-rails) or [JavaScript bundler](https://github.com/rails/jsbundling-rails) to manage your application's JavaScript. If you're using an import map, the Stimulus dependencies will be pinned to the versions of the library included with this gem. If you're using Node, yarn will add the dependencies to your `package.json` file.
15
15
 
16
+ The installer amends your JavaScript entry point at `app/javascript/application.js` to import the `app/javascript/controllers/index.js` file, which is responsible for setting up your Stimulus application and registering your controllers.
16
17
 
17
- ## Usage
18
18
 
19
- The installer amends your JavaScript entry point at `app/javascript/application.js` to import the `app/javascript/controllers/index.js` file, which is responsible for setting up your Stimulus application and registering your controllers.
19
+ ## Usage with import map
20
+
21
+ With an import-mapped application, controllers are automatically pinned and registered based on the file structure. The installer will amend your `config/importmap.rb` to configure this such that all controllers in `app/javascript/controllers` are pinned.
22
+
23
+ By default, your application will be setup to eager load all the controllers mentioned in your import map under "controllers". This works well together with preloading in the import map when you have a modest number of controllers.
24
+
25
+ If you have a lot of controllers, you may well want to lazy load them instead. This can be done by changing from `eagerLoadControllersFrom` to `lazyLoadControllersFrom` in your `app/javascript/controllers/index.js` file.
26
+
27
+ When lazy loading, controllers are not loaded until their data-controller identifier is encountered in the DOM.
28
+
20
29
 
21
- With an import-mapped application, controllers are automatically pinned and registered based on the file structure. With a node application, controllers need to be imported and registered directly in the index.js file, but this is done automatically using either the Stimulus generator (`./bin/rails generate stimulus [controller]`) or the dedicated `stimulus:manifest:update` task. Either will overwrite the `controllers/index.js` file.
30
+ ## Usage with JavaScript bundler
31
+
32
+ With an application using a JavaScript bundler, controllers need to be imported and registered directly in the index.js file. But this can be done automatically using either the Stimulus generator (`./bin/rails generate stimulus [controller]`) or the dedicated `stimulus:manifest:update` task. Either will overwrite the `controllers/index.js` file.
22
33
 
23
34
  You're encouraged to use the generator to add new controllers like so:
24
35
 
@@ -38,23 +49,6 @@ export default class extends Controller {
38
49
  }
39
50
  ```
40
51
 
41
- And it'll be activated and registered automatically when encountering the data-controller attribute in your DOM:
42
-
43
- ```html
44
- <div data-controller="hello">
45
- <input data-hello-target="name" type="text">
46
-
47
- <button data-action="click->hello#greet">
48
- Greet
49
- </button>
50
-
51
- <span data-hello-target="output">
52
- </span>
53
- </div>
54
- ```
55
-
56
- That's it!
57
-
58
52
 
59
53
  ## License
60
54
 
@@ -50,3 +50,5 @@ new MutationObserver((mutationsList) => {
50
50
  }).observe(document, { attributeFilter: [controllerAttribute], subtree: true, childList: true })
51
51
 
52
52
  autoloadControllersWithin(document)
53
+
54
+ console.warn("stimulus-autoload.js has been deprecated in favor of stimulus-loading.js")
@@ -23,3 +23,5 @@ function registerControllerFromPath(path, under, application) {
23
23
  .then(module => application.register(name, module.default))
24
24
  .catch(error => console.log(`Failed to register controller: ${name} (${path})`, error))
25
25
  }
26
+
27
+ console.warn("stimulus-importmap-autoload.js has been deprecated in favor of stimulus-loading.js")
@@ -0,0 +1,81 @@
1
+ // FIXME: es-module-shim won't shim the dynamic import without this explicit import
2
+ import "@hotwired/stimulus"
3
+
4
+ const controllerAttribute = "data-controller"
5
+ const registeredControllers = {}
6
+
7
+ // Eager load all controllers registered beneath the `under` path in the import map to the passed application instance.
8
+ export function eagerLoadControllersFrom(under, application) {
9
+ const paths = Object.keys(parseImportmapJson()).filter(path => path.match(new RegExp(`^${under}/.*_controller$`)))
10
+ paths.forEach(path => registerControllerFromPath(path, under, application))
11
+ }
12
+
13
+ function parseImportmapJson() {
14
+ return JSON.parse(document.querySelector("script[type=importmap]").text).imports
15
+ }
16
+
17
+ function registerControllerFromPath(path, under, application) {
18
+ const name = path
19
+ .replace(new RegExp(`^${under}/`), "")
20
+ .replace("_controller", "")
21
+ .replace(/\//g, "--")
22
+ .replace(/_/g, "-")
23
+
24
+ import(path)
25
+ .then(module => registerController(name, module, application))
26
+ .catch(error => console.debug(`Failed to register controller: ${name} (${path})`, error))
27
+ }
28
+
29
+
30
+ // Lazy load controllers registered beneath the `under` path in the import map to the passed application instance.
31
+ export function lazyLoadControllersFrom(under, application, element = document) {
32
+ lazyLoadExistingControllers(under, application, element)
33
+ lazyLoadNewControllers(under, application, element)
34
+ }
35
+
36
+ function lazyLoadExistingControllers(under, application, element) {
37
+ queryControllerNamesWithin(element).forEach(controllerName => loadController(controllerName, under, application))
38
+ }
39
+
40
+ function lazyLoadNewControllers(under, application, element) {
41
+ new MutationObserver((mutationsList) => {
42
+ for (const { attributeName, target, type } of mutationsList) {
43
+ switch (type) {
44
+ case "attributes": {
45
+ if (attributeName == controllerAttribute && target.getAttribute(controllerAttribute)) {
46
+ extractControllerNamesFrom(target).forEach(controllerName => loadController(controllerName, under, application))
47
+ }
48
+ }
49
+
50
+ case "childList": {
51
+ lazyLoadExistingControllers(under, application, target)
52
+ }
53
+ }
54
+ }
55
+ }).observe(element, { attributeFilter: [controllerAttribute], subtree: true, childList: true })
56
+ }
57
+
58
+ function queryControllerNamesWithin(element) {
59
+ return Array.from(element.querySelectorAll(`[${controllerAttribute}]`)).map(extractControllerNamesFrom).flat()
60
+ }
61
+
62
+ function extractControllerNamesFrom(element) {
63
+ return element.getAttribute(controllerAttribute).split(/\s+/).filter(content => content.length)
64
+ }
65
+
66
+ function loadController(name, under, application) {
67
+ import(controllerFilename(name, under))
68
+ .then(module => registerController(name, module, application))
69
+ .catch(error => console.debug(`Failed to autoload controller: ${name}`, error))
70
+ }
71
+
72
+ function controllerFilename(name, under) {
73
+ return `${under}/${name.replace(/--/g, "/").replace(/-/g, "_")}_controller`
74
+ }
75
+
76
+ function registerController(name, module, application) {
77
+ if (name in registeredControllers) return
78
+
79
+ application.register(name, module.default)
80
+ registeredControllers[name] = true
81
+ }
@@ -1,5 +1,6 @@
1
1
  //= link ./stimulus-autoloader.js
2
2
  //= link ./stimulus-importmap-autoloader.js
3
+ //= link ./stimulus-loading.js
3
4
 
4
5
  /*
5
6
  Stimulus 3.0.1
@@ -1,5 +1,6 @@
1
1
  //= link ./stimulus-autoloader.js
2
2
  //= link ./stimulus-importmap-autoloader.js
3
+ //= link ./stimulus-loading.js
3
4
 
4
5
  /*
5
6
  Stimulus 3.0.1
@@ -1,5 +1,11 @@
1
1
  // Import and register all your controllers from the importmap under controllers/*
2
2
 
3
3
  import { application } from "controllers/application"
4
- import { registerControllersFrom } from "@hotwired/stimulus-importmap-autoloader"
5
- registerControllersFrom("controllers", application)
4
+
5
+ // Eager load all controllers defined in the import map under controllers/**/*_controller
6
+ import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
7
+ eagerLoadControllersFrom("controllers", application)
8
+
9
+ // Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
10
+ // import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
11
+ // lazyLoadControllersFrom("controllers", application)
@@ -13,7 +13,7 @@ append_to_file "app/javascript/application.js", %(import "controllers"\n)
13
13
  say "Pin Stimulus"
14
14
  append_to_file "config/importmap.rb" do <<-RUBY
15
15
  pin "@hotwired/stimulus", to: "stimulus.js"
16
- pin "@hotwired/stimulus-importmap-autoloader", to: "stimulus-importmap-autoloader.js"
16
+ pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
17
17
  pin_all_from "app/javascript/controllers", under: "controllers"
18
18
  RUBY
19
19
  end
@@ -1,3 +1,3 @@
1
1
  module Stimulus
2
- VERSION = "0.6.2"
2
+ VERSION = "0.7.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -37,6 +37,7 @@ files:
37
37
  - Rakefile
38
38
  - app/assets/javascripts/stimulus-autoloader.js
39
39
  - app/assets/javascripts/stimulus-importmap-autoloader.js
40
+ - app/assets/javascripts/stimulus-loading.js
40
41
  - app/assets/javascripts/stimulus.js
41
42
  - app/assets/javascripts/stimulus.min.js
42
43
  - lib/generators/stimulus/USAGE