svelte-on-rails 5.0.0 → 5.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 702cfaf256c84b2e8f17356ed333b63e14d4d1252f7e1e2dabd1698d350a4461
4
- data.tar.gz: d7b63bfce50f3aba78c2bfd5f646bba5e02e0ae351d6cf4cc6129b8ba4ce26f4
3
+ metadata.gz: 0e2782073f696f72736004ae21d57a71e4429fb878f915954e36628e16904de9
4
+ data.tar.gz: 2d041a60e7908ce20ab64f490ccebe3d3c673882986c83a64981aaf1e9931768
5
5
  SHA512:
6
- metadata.gz: f86aafc1b3e91cbe2eff633fc40325dc048f00d5d668d52f7ea03c130f9171ecea1101a63c871883ac8ec173dfbaaa5932cb37e1de83a49fea5e3c09993463ef
7
- data.tar.gz: 197a951604f5dcdf6c64bf7ccfcfe0fd65cd91e2ae8cb6d55c53de3bcd0b0821292856ba2cfdffb56f72a3b3d6e93b76a4e63ea08c8eb16548a03b4166cdcf10
6
+ metadata.gz: 5d1fef990a79dfa782b0101f33ed64f3631d126ea6ef16dfde8d21d240653d8d938a87689955af288b862362216fbb760db61e79d709c512b242d0f86ad823d1
7
+ data.tar.gz: 430b9cf7ab45fb7e0ab629b4de95bd262e8b02bd68a58793dcd614832dfd2bb04d63f52d20ddc6639dc951d8ae132188dee755dadab1042f98a0268dcf4bab63
data/README.md CHANGED
@@ -346,45 +346,133 @@ on the svelte-on-rails config file or pass the `expires_in` as argument to the v
346
346
 
347
347
  Pass `debug: true` to the helper and you will see on the logs how your configuration works.
348
348
 
349
- # Turbo::StreamsChannel.send!
349
+ ## ActionCable / TurboStream
350
+
351
+ There are two ways that the server can talk to the client over Websocket:
352
+
353
+ - ActionCable transmits directly to the frontends javascript
354
+ - TurboStreams is a wrapper around ActionCable
355
+ - You always need a html part for communication
356
+
357
+ **Configs**
358
+
359
+ Check the regarding keys and their commends on the [config file](https://gitlab.com/sedl/svelte-on-rails/-/blob/main/templates/config_base/config/svelte_on_rails.yml?ref_type=heads).
360
+ From there, you just need:
361
+
362
+ ```yaml
363
+ turbo_stream:
364
+ target_html_id: 'svelte-on-rails-stream-actions-box'
365
+ channel: 'public'
366
+ ```
367
+
368
+ ## ActionCable!
369
+
370
+ ActionCable is the more basic library behind `TurboStream` and it is a second Option to call Javascript Actions from the server.
371
+
372
+ **Setup**
373
+
374
+ Add `app/channels/svelte_on_rails_channel.rb`
375
+
376
+ ```ruby
377
+ class SvelteOnRailsChannel < ApplicationCable::Channel
378
+ def subscribed
379
+ stream_from "svelte_on_rails_channel"
380
+ end
381
+
382
+ def unsubscribed
383
+ # Any cleanup needed when channel is unsubscribed
384
+ end
385
+ end
386
+ ```
387
+
388
+ run
389
+
390
+ ```shell
391
+ npm i @rails/actioncable
392
+ ```
393
+
394
+ Add to `application.js`
395
+
396
+ ```javascript
397
+ import { createConsumer } from "@rails/actioncable"
398
+ import {dispatchSvelteStreamEvent, actionCableDebugLog} from '@csedl/svelte-on-rails'
399
+
400
+ const consumer = createConsumer()
401
+
402
+ consumer.subscriptions.create("SvelteOnRailsChannel", {
403
+ connected() {
404
+ actionCableDebugLog("Connected to SvelteOnRailsChannel")
405
+ },
406
+ disconnected() {
407
+ actionCableDebugLog("Disconnected from SvelteOnRailsChannel")
408
+ },
409
+ received(data) {
410
+ actionCableDebugLog("Received:", data)
411
+ dispatchSvelteStreamEvent(data)
412
+ }
413
+ })
414
+ ```
415
+
416
+ By setting `debug = true` [node package](https://www.npmjs.com/package/@csedl/svelte-on-rails) you see what it is doing.
417
+
418
+ **WhatdispatchSvelteStreamEvent does**
419
+
420
+ - Without the attribute `component` given,
421
+ it searches for all elements with the class `svelte-component` and fires the event `channel-action`
422
+ - When `selector` is given, it searches for all matching elements within each component.
423
+ - The event can be overriden by the argument `event`
424
+
425
+ **Usage**
350
426
 
351
- There are some methods that making it easier to let the server speak to the Components on the front.
427
+ Now you can dispatch events on the component by:
352
428
 
353
- Theese are independent class methods that can be executed from every place on the app.
429
+ ```ruby
430
+ ActionCable.server.broadcast("svelte_on_rails_channel",
431
+ {
432
+ eventDetail: { message: "Sent by ActionCable: äöü🤣🌴🌍漢字" },
433
+ component: '/javascript/components/ReceiveFromChannel',
434
+ }
435
+ )
436
+ ```
437
+
438
+ # Turbo::StreamsChannel.send!
354
439
 
355
440
  Few setup is needed for that:
356
441
 
357
442
  **Setup**
358
443
 
359
- Please setup the `turbo-rails` gem and follow the chapter [Come alive with Turbo Streams](https://github.com/hotwired/turbo-rails?tab=readme-ov-file#come-alive-with-turbo-streams)
444
+ Please setup the `turbo-rails` gem and follow the chapter [Come alive with Turbo Streams](https://github.com/hotwired/turbo-rails?tab=readme-ov-file#come-alive-with-turbo-streams), which mainly is:
445
+
446
+ ```shell
447
+ bundle add turbo-rails
448
+ rails turbo:install
449
+ ```
450
+
451
+ make sure that `import "@hotwired/turbo-rails"` is on your application.js and set the view helper
452
+ `<%= turbo_stream_from 'public' %>` to your view.
360
453
 
361
- If a channel - let's call us it `public` is working and you have a html-tag on the front
362
- with a ID - let's call us it `svelte-on-rails-stream-actions-box` (This can be any element,
363
- you could just give the body-tag a ID // it is just the way hotwired works)
364
- and a code Block like
454
+ If a channel (e.g.: `public`) is active and you have an HTML element with a HTML-ID (e.g.: `svelte-on-rails-stream-actions-box`),
455
+ you can test it by:
365
456
 
366
457
  ```ruby
367
458
  Turbo::StreamsChannel.send(
368
459
  "broadcast_append_to",
369
460
  'public',
370
461
  target: 'svelte-on-rails-stream-actions-box',
371
- content: "<div>Hello World</div>"
462
+ content: "<div>Turbo-Streams are working!</div>"
372
463
  )
373
464
  ```
374
465
 
375
- is exposing a «Hello World» on the front then you are good to go.
376
- Please check the regarding keys and theyr commends on the [config file](https://gitlab.com/sedl/svelte-on-rails/-/blob/main/templates/config_base/config/svelte_on_rails.yml?ref_type=heads).
377
-
378
- **Usage Example: Component Event**
466
+ When this works you are good to go.
379
467
 
380
- The easiest way on the svelte component is:
468
+ **Minimal Usage Example**
381
469
 
382
470
  ```sveltehtml
383
471
  <script>
384
472
  import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
385
473
 
386
- function handleCableEvent(event) {
387
- console.log(event.detail.message)
474
+ function handleCableEvent() {
475
+ console.log('Event received by Turbo Stream')
388
476
  }
389
477
  </script>
390
478
  <!--on any element:-->
@@ -394,44 +482,45 @@ The easiest way on the svelte component is:
394
482
  And call this by:
395
483
 
396
484
  ```ruby
397
- SvelteOnRails::TurboStream.new.dispatch_event(
398
- event_detail: { message: "Special Chars from the server: äöü🤣🌴🌍漢字" }
399
- )
485
+ SvelteOnRails::TurboStream.new.dispatch_event
400
486
  ```
487
+ **What it does**
401
488
 
402
- **What is this doing?**
403
-
404
- - The `addComponentStreamListener` adds a `eventListener` on the Element, that wraps each
405
- component that is rendered by the view helper `svelte_component`, found by `currentElement.closest('.svelte-component')`
406
- - A Stimulus controller is pushed to all subscribers of the configured channel.
407
- - You can override this by passing `stream_name` to the method.
408
- - Without the attribute `component` given,
409
- it searches for all elements with the class `svelte-component` and fires the event `channel-action`
410
- - When `selector` is given, it searches for all matching elements within each component.
411
- - The event can be overriden by the argument `event`
412
-
413
- By setting `debug = true` [node package](https://www.npmjs.com/package/@csedl/svelte-on-rails) you see what it is doing.
489
+ - The `addComponentStreamListener` adds the eventListener `stream-action` on the wrapping Element
490
+ - The «wrapping Element» is the Element from the view helper `svelte_component` with the class `svelte-component`.
491
+ - A Stimulus controller is pushed to all subscribers of the configured channel.
492
+ - You can override the channel name by passing `channel` to the method.
414
493
 
415
- **Usage Example: Event on components element**
494
+ **Usage Example, more detailed**
416
495
 
417
496
  If you want to fire a event on a specific element within the component, you do not need `addComponentStreamListener`.
418
- Just do something like
497
+ Just do something like:
419
498
 
420
499
  ```sveltehtml
421
- <button class="counter-button" onclick="{increaseCounter}">increase {counter}</button>
500
+ <script>
501
+ function logStreamMessage(event) {
502
+ console.log(event.detail.message)
503
+ }
504
+ </script>
505
+ <button class="counter-button" onclick="{logStreamMessage}">Show Contents</button>
422
506
  ```
423
507
 
424
- within the svelte component and call it by
508
+ within the svelte component.
509
+
510
+ Then, call it by:
425
511
 
426
512
  ```ruby
427
513
  SvelteOnRails::TurboStream.new.dispatch_event(
428
- event: 'click',
514
+ channel: 'my-custom-stream',
515
+ component: '/javascript/components/TurboStreamsChannel',
429
516
  selector: '.counter-button',
430
- component: '/javascript/components/TurboStreamsChannel'
517
+ event: 'click',
518
+ event_detail: { message: "Greetings from Server: äöü🤣🌴🌍漢字" }
431
519
  )
432
520
  ```
433
521
 
434
522
 
523
+
435
524
  ## More rake tasks
436
525
 
437
526
  This tasks are more for testing/playground purposes
@@ -1,6 +1,7 @@
1
1
  require "svelte_on_rails/configuration"
2
2
  require "svelte_on_rails/view_helpers"
3
3
  require "svelte_on_rails/turbo_stream"
4
+ require "svelte_on_rails/action_cable"
4
5
  require "svelte_on_rails/railtie" if defined?(Rails)
5
6
 
6
7
  require "svelte_on_rails/renderer/renderer"
@@ -0,0 +1,42 @@
1
+ module SvelteOnRails
2
+ class ActionCable
3
+ def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, channel: "svelte_on_rails_channel")
4
+
5
+ if event != 'stream-action' && !selector
6
+ raise "Another event name than the default one is only possible together with a selector"
7
+ end
8
+
9
+ args = {
10
+ eventDetail: event_detail,
11
+ component: component,
12
+ event: event,
13
+ selector: selector
14
+ }
15
+
16
+ #args_enc = Base64.strict_encode64(args.to_json)
17
+
18
+ ActionCable.server.broadcast(channel, args)
19
+
20
+ end
21
+
22
+ private
23
+
24
+ def configs
25
+ @configs ||= begin
26
+
27
+ conf = SvelteOnRails::Configuration.instance
28
+ unless conf.configs[:turbo_stream]
29
+ raise '[svelte-on-rails] missing configuration: :turbo_stream'
30
+ end
31
+ unless conf.configs[:turbo_stream]['target_html_id']
32
+ raise '[svelte-on-rails] missing configuration: turbo_stream/target_html_id'
33
+ end
34
+ unless conf.configs[:turbo_stream]['channel']
35
+ raise '[svelte-on-rails] missing configuration: turbo_stream/channel'
36
+ end
37
+
38
+ conf.configs[:turbo_stream]
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,6 +1,10 @@
1
1
  module SvelteOnRails
2
2
  class TurboStream
3
- def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, stream_name: nil)
3
+ def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, channel: nil)
4
+
5
+ if event != 'stream-action' && !selector
6
+ raise "Another event name than the default one is only possible together with a selector"
7
+ end
4
8
 
5
9
  args = {
6
10
  eventDetail: event_detail,
@@ -13,7 +17,7 @@ module SvelteOnRails
13
17
 
14
18
  Turbo::StreamsChannel.send(
15
19
  "broadcast_append_to",
16
- stream_name || configs['stream_name'],
20
+ channel || configs['channel'],
17
21
  target: configs['target_html_id'],
18
22
  content: "<div style=\"display: none;\" data-controller=\"svelte-on-rails-turbo-stream\" data-args=\"#{args_enc}\"></div>"
19
23
  )
@@ -32,8 +36,8 @@ module SvelteOnRails
32
36
  unless conf.configs[:turbo_stream]['target_html_id']
33
37
  raise '[svelte-on-rails] missing configuration: turbo_stream/target_html_id'
34
38
  end
35
- unless conf.configs[:turbo_stream]['stream_name']
36
- raise '[svelte-on-rails] missing configuration: turbo_stream/stream_name'
39
+ unless conf.configs[:turbo_stream]['channel']
40
+ raise '[svelte-on-rails] missing configuration: turbo_stream/channel'
37
41
  end
38
42
 
39
43
  conf.configs[:turbo_stream]
@@ -25,7 +25,7 @@ turbo_stream:
25
25
  # this part you need when you want to be able to trigger javascript actions on svelte-components from the backend
26
26
  target_html_id: 'svelte-on-rails-stream-actions-box'
27
27
  # html-id of any element that must exist for being able to receive actions (turbo streams can only work this way)
28
- stream_name: 'public'
28
+ channel: 'public'
29
29
 
30
30
  development:
31
31
  watch_changes: true
@@ -0,0 +1,9 @@
1
+ class SvelteOnRailsChannel < ApplicationCable::Channel
2
+ def subscribed
3
+ stream_from "svelte_on_rails_channel"
4
+ end
5
+
6
+ def unsubscribed
7
+ # Any cleanup needed when channel is unsubscribed
8
+ end
9
+ end
@@ -9,17 +9,27 @@ class SvelteOnRailsHelloWorldController < ApplicationController
9
9
  SvelteOnRails::TurboStream.new.dispatch_event(
10
10
  event: 'click',
11
11
  selector: '.counter-button',
12
- component: '/javascript/components/TurboStreamsChannel'
12
+ component: '/javascript/components/ReceiveFromChannel'
13
13
  )
14
14
  render plain: 'increase-action streamed'
15
+ elsif params['action_cable']
16
+
17
+ ActionCable.server.broadcast("svelte_on_rails_channel",
18
+ {
19
+ eventDetail: { message: "Sent by ActionCable: äöü🤣🌴🌍漢字" },
20
+ component: '/javascript/components/ReceiveFromChannel',
21
+ }
22
+ )
23
+ #SvelteOnRails::ActionCable.new.dispatch_event(channel: "svelte_on_rails_channel", event_detail: { message: "Hello from SvelteChannel!" })
24
+
25
+ render plain: 'ActionCable streaming'
15
26
  else
16
27
  SvelteOnRails::TurboStream.new.dispatch_event(
17
- event_detail: { message: "Special Chars from the server: äöü🤣🌴🌍漢字", user: "Müller" }
28
+ event_detail: { message: "Sent by TurboStream: äöü🤣🌴🌍漢字", user: "Müller" }
18
29
  )
19
30
  render plain: 'component-action streamed'
20
31
  end
21
32
 
22
- head :ok
23
33
  end
24
34
 
25
35
  end
@@ -7,7 +7,6 @@
7
7
  let results = $state([])
8
8
  let incrBtn
9
9
 
10
-
11
10
  onMount(() => {
12
11
  incrBtn.addEventListener('click', increaseCounter)
13
12
  });
@@ -31,7 +30,7 @@
31
30
  const handleCableEvent = (ev) => {
32
31
  results.push(
33
32
  {
34
- text: `Message received from TurboStream: ${JSON.stringify(ev.detail.message)}`,
33
+ text: `Message received from Server: ${JSON.stringify(ev.detail.message)}`,
35
34
  class: 'stream-action-received'
36
35
  }
37
36
  )
@@ -49,6 +48,8 @@
49
48
 
50
49
  <button class="call-channel-action" onclick="{callChannelAction}">Action</button>
51
50
 
51
+ <button onclick="{() => callChannelAction('action_cable=true')}">Call ActionCable Action</button>
52
+
52
53
  <ul class="results">
53
54
  {#each results as result}
54
55
  <li class="{result.class}">{result.text}</li>
@@ -6,7 +6,7 @@
6
6
  <%= render 'nav' %>
7
7
 
8
8
 
9
- <%= svelte_component "TurboStreamsChannel" %>
9
+ <%= svelte_component "ReceiveFromChannel" %>
10
10
 
11
11
  <%= content_tag :div, id: 'svelte-on-rails-stream-actions-box' do %>
12
12
  <% end %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svelte-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Sedlmair
@@ -31,6 +31,7 @@ files:
31
31
  - README.md
32
32
  - lib/generators/svelte_on_rails/install/install_generator.rb
33
33
  - lib/svelte-on-rails.rb
34
+ - lib/svelte_on_rails/action_cable.rb
34
35
  - lib/svelte_on_rails/configuration.rb
35
36
  - lib/svelte_on_rails/installer/gem_utils.rb
36
37
  - lib/svelte_on_rails/installer/haml.rb
@@ -53,6 +54,7 @@ files:
53
54
  - templates/config_base/app/frontend/ssr/ssr.js
54
55
  - templates/config_base/config/svelte_on_rails.yml
55
56
  - templates/config_base/vite-ssr.config.ts
57
+ - templates/rails_vite_hello_world/app/channels/svelte_on_rails_channel.rb
56
58
  - templates/rails_vite_hello_world/app/controllers/svelte_on_rails_hello_world_controller.rb
57
59
  - templates/rails_vite_hello_world/app/frontend/images/svelte-on-rails-hello-world-england.png
58
60
  - templates/rails_vite_hello_world/app/frontend/images/svelte-on-rails-hello-world-face-smile-wink.svg
@@ -61,9 +63,9 @@ files:
61
63
  - templates/rails_vite_hello_world/app/frontend/javascript/components/JpgImport.svelte
62
64
  - templates/rails_vite_hello_world/app/frontend/javascript/components/ParentWithChild.svelte
63
65
  - templates/rails_vite_hello_world/app/frontend/javascript/components/PngImport.svelte
66
+ - templates/rails_vite_hello_world/app/frontend/javascript/components/ReceiveFromChannel.svelte
64
67
  - templates/rails_vite_hello_world/app/frontend/javascript/components/SvelteOnRailsHelloWorld.svelte
65
68
  - templates/rails_vite_hello_world/app/frontend/javascript/components/SvgRawImport.svelte
66
- - templates/rails_vite_hello_world/app/frontend/javascript/components/TurboStreamsChannel.svelte
67
69
  - templates/rails_vite_hello_world/app/frontend/javascript/components/sub/NestedComponent.svelte
68
70
  - templates/rails_vite_hello_world/app/frontend/javascript/nestedJavascript.js
69
71
  - templates/rails_vite_hello_world/app/frontend/javascript/nestedJavascriptToggled.js