svelte-on-rails 4.1.1 → 5.0.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: f1113ad80ad88261fdf387b8d033006e10cedcbb0bd4e941a5a6fd8d7c338e2e
4
- data.tar.gz: de7a37961949e4ff3f99de2da8818e159b3afc552dd530f1373607101c2a50db
3
+ metadata.gz: 702cfaf256c84b2e8f17356ed333b63e14d4d1252f7e1e2dabd1698d350a4461
4
+ data.tar.gz: d7b63bfce50f3aba78c2bfd5f646bba5e02e0ae351d6cf4cc6129b8ba4ce26f4
5
5
  SHA512:
6
- metadata.gz: e173b7d27296c0a51f7ea6d35632fab227e34964353087354fcd10634efc004959140da5724094b486dbb0a009e10af7a65e809d152b5621ac82911d5efc5198
7
- data.tar.gz: 0d8f6bc08236e2752c81c7f1353f36c41c67ea9e4937410658ead038351b1ff0a323992af634b8b084e36d017facb6775cc41b0efa3cabd2989f5cd47620d81d
6
+ metadata.gz: f86aafc1b3e91cbe2eff633fc40325dc048f00d5d668d52f7ea03c130f9171ecea1101a63c871883ac8ec173dfbaaa5932cb37e1de83a49fea5e3c09993463ef
7
+ data.tar.gz: 197a951604f5dcdf6c64bf7ccfcfe0fd65cd91e2ae8cb6d55c53de3bcd0b0821292856ba2cfdffb56f72a3b3d6e93b76a4e63ea08c8eb16548a03b4166cdcf10
data/README.md CHANGED
@@ -12,34 +12,35 @@ Svelte.
12
12
 
13
13
  Vite.
14
14
 
15
- Hotwired.
16
-
17
- # Why Svelte?
18
-
19
- On every app there are parts where you want it to shine. This is where Svelte comes in.
20
-
21
- - Works perfectly with Hotwired/Turbo
22
- - Perfect addition to Stimulus
23
- - Easy to learn
24
- - Powerful
25
- - Super fast
26
- - **Compared to Stimulus**
27
- - No more writing double logic of the initial HTML state
28
- - One Logic in one file!
29
- - Render logic and script logic is in one file and, maybe, some css too.
30
- - Stimulus is great for rails views with some javascript, but, complex parts: You will love svelte.
31
- - Improved Backend Response Time: Certain HTML components can be rendered directly by frontend JavaScript.
15
+ # Why Choose Svelte for Integration?
16
+
17
+ Svelte delivers the robust frontend experience missing from DHH’s
18
+ vision while aligning seamlessly with Rails’ full-stack philosophy.
19
+
20
+ - **Seamless Integration**
21
+ - Works flawlessly with Hotwired/Turbo
22
+ - Complements Hotwired perfectly
23
+ - **Developer-Friendly**
24
+ - Easy to learn
25
+ - Intuitive and powerful
26
+ - Lightning-fast performance
27
+ - **Compared to Single Page Apps (SPAs)**
28
+ - Full-stack development delivers maximum value:
29
+ - Unified testing from database to frontend
30
+ - Single-source system delivery
31
+ - For the most HTML Hotwired is enough
32
+ - **Compared to Hotwired**
33
+ - Stimulus is not a tool for writing frontend-apps
34
+ - Svelte eliminates redundant HTML state logic
35
+ - Consolidates component logic into a single file
36
+ - Offloads rendering of certain HTML components to frontend JavaScript, reducing server load
32
37
  - **Compared to React**
33
- - No more shadow dom and all those packages that are supposed to improve performance (e.g. useCallback...)
34
- - Slimmer packages
35
- - Easier to learn
36
- - Faster
38
+ - Watch Rich Harris’ [Rethinking Reactivity](https://svelte.dev/blog/svelte-3-rethinking-reactivity) (3:50–6:40) for a compelling comparison
39
+ - No shadow DOM or performance-heavy packages (e.g., useCallback)
40
+ - Leaner, slimmer packages
41
+ - Easier to learn and faster performance
37
42
 
38
- Have a look at this entertaining video [rethinking reactivity](https://svelte.dev/blog/svelte-3-rethinking-reactivity)
39
- by Rich Harris, especially from 3:50 to 6:40 and his comparison to react.
40
-
41
- This all fits in perfectly with the Rails way of minimalist javascript,
42
- but: Where needed, we want full power.
43
+ Svelte empowers Rails’ full-stack vision with modern, streamlined frontend integration.
43
44
 
44
45
  # Features
45
46
 
@@ -314,13 +315,13 @@ When using the `cached_svelte_component` helper you must have the `redis` gem in
314
315
 
315
316
  This caches on a key like `svelte-on-rails:development:SvelteOnRailsHelloWorld.svelte-1xq5tnu-User1:fscyhz-18bm76a` which includes:
316
317
 
317
- - gem name and environment
318
+ - Namespace, if configured, otherwise the default is gem-name and environment
318
319
  - component filename
319
- - hash of the file-path
320
+ - checksum of the file-path
320
321
  - `cache_key` if given as argument to the view-helper
321
322
  - can be a array of active-record objects or strings or a single element instead of a array
322
- - hash of the last modification timestamp of the component (only when `watch_changes` is set to true)
323
- - hash of the given attributes
323
+ - checksum of the last modification timestamp of the component (only when `watch_changes` is set to true)
324
+ - checksum of the given attributes
324
325
 
325
326
  **Configuration**
326
327
 
@@ -339,12 +340,98 @@ redis_cache_store:
339
340
  expires_in: 2.hours
340
341
  ```
341
342
 
342
- on the svelte-on-rails config file.
343
+ on the svelte-on-rails config file or pass the `expires_in` as argument to the view helper.
343
344
 
344
345
  **Check if it works**
345
346
 
346
347
  Pass `debug: true` to the helper and you will see on the logs how your configuration works.
347
348
 
349
+ # Turbo::StreamsChannel.send!
350
+
351
+ There are some methods that making it easier to let the server speak to the Components on the front.
352
+
353
+ Theese are independent class methods that can be executed from every place on the app.
354
+
355
+ Few setup is needed for that:
356
+
357
+ **Setup**
358
+
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)
360
+
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
365
+
366
+ ```ruby
367
+ Turbo::StreamsChannel.send(
368
+ "broadcast_append_to",
369
+ 'public',
370
+ target: 'svelte-on-rails-stream-actions-box',
371
+ content: "<div>Hello World</div>"
372
+ )
373
+ ```
374
+
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**
379
+
380
+ The easiest way on the svelte component is:
381
+
382
+ ```sveltehtml
383
+ <script>
384
+ import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
385
+
386
+ function handleCableEvent(event) {
387
+ console.log(event.detail.message)
388
+ }
389
+ </script>
390
+ <!--on any element:-->
391
+ <h1 use:addComponentStreamListener={handleCableEvent}>Test TurboStreams Channel</h1>
392
+ ```
393
+
394
+ And call this by:
395
+
396
+ ```ruby
397
+ SvelteOnRails::TurboStream.new.dispatch_event(
398
+ event_detail: { message: "Special Chars from the server: äöü🤣🌴🌍漢字" }
399
+ )
400
+ ```
401
+
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.
414
+
415
+ **Usage Example: Event on components element**
416
+
417
+ If you want to fire a event on a specific element within the component, you do not need `addComponentStreamListener`.
418
+ Just do something like
419
+
420
+ ```sveltehtml
421
+ <button class="counter-button" onclick="{increaseCounter}">increase {counter}</button>
422
+ ```
423
+
424
+ within the svelte component and call it by
425
+
426
+ ```ruby
427
+ SvelteOnRails::TurboStream.new.dispatch_event(
428
+ event: 'click',
429
+ selector: '.counter-button',
430
+ component: '/javascript/components/TurboStreamsChannel'
431
+ )
432
+ ```
433
+
434
+
348
435
  ## More rake tasks
349
436
 
350
437
  This tasks are more for testing/playground purposes
@@ -398,10 +485,14 @@ This will cause the installer, to install the npm package from a local path inst
398
485
 
399
486
  Then run the tests and start contributing.
400
487
 
488
+ **RUN THE FIRST TEST (!)**: Testing is complex here because of the design based on the installer test.
489
+ On Problems, i always run the `Installer > destroy and create rails app > FIRST TEST > [...] check if javascript works`. When this passes,
490
+ all the others passing mostly.
491
+
401
492
  Tests are based on the included templates, like the `hello world template` and on the installer.
402
493
 
403
494
  Here I learned how to write tests! Testing installers is heavy, you will read about it in the
404
- test_helpers. But I have done my best to give all the code a clear structure.
495
+ test_helpers. But I have done my best to give all the code a clear structure.
405
496
  I hope you like it, and improvements are welcome.
406
497
 
407
498
  **Installer tests** starting with completely destroy the rails app within the `generated_test_app_path`,
@@ -9,6 +9,7 @@ module SvelteOnRails
9
9
  class_option :vite, type: :boolean, default: false, desc: "Use Vite"
10
10
  class_option :haml, type: :boolean, default: false, desc: "Use Haml"
11
11
  class_option :turbo, type: :boolean, default: false, desc: "Use @hotwired/turbo-rails"
12
+ class_option :turbo_streams, type: :boolean, default: false, desc: "Turbo::StreamsChannel"
12
13
  class_option :svelte, type: :boolean, default: false, desc: "Install Svelte"
13
14
  class_option :pug, type: :boolean, default: false, desc: "Install Pug"
14
15
  class_option :hello_world, type: :boolean, default: false, desc: "Create Hello World component"
@@ -88,6 +89,20 @@ module SvelteOnRails
88
89
  js_i = SvelteOnRails::Installer::Javascript
89
90
  js_i.append_import_statement(application_js_path, tr_pkg, "import '#{tr_pkg}';")
90
91
 
92
+ return unless options[:turbo_streams] || options[:full]
93
+
94
+ puts '-' * 80
95
+ puts ' ▶︎▶︎▶︎ INSTALLING Turbo::StreamsChannel'
96
+ puts '-' * 80
97
+
98
+ gem_uts = SvelteOnRails::GemUtils
99
+ puts '• installing turbo-rails ...'
100
+ gem_uts.install_gem('turbo-rails')
101
+ puts '• installed turbo-rails!'
102
+ utils_i = SvelteOnRails::Installer::Utils
103
+ puts '• running turbo:install ...'
104
+ utils_i.run_command('bundle exec rails turbo:install', success_message: 'You must import')
105
+ puts '• turbo:install finished!'
91
106
  end
92
107
 
93
108
  def svelte
@@ -112,6 +127,12 @@ module SvelteOnRails
112
127
  puts '-' * 80
113
128
 
114
129
  hw_i = SvelteOnRails::Installer::HelloWorld
130
+
131
+ utils_i = SvelteOnRails::Installer::Utils
132
+ utils_i.add_route(" get \"svelte_on_rails_hello_world/turbo_streams_channel\"", app_root: Rails.root)
133
+ utils_i.add_route(" get \"svelte_on_rails_hello_world/turbo_stream_action\"", app_root: Rails.root)
134
+ npm_i = SvelteOnRails::Installer::Npm
135
+ npm_i.install_or_update_package('axios')
115
136
  @hello_world_path = hw_i.install_hello_world(['rails_vite_hello_world'], app_root: nil, force: true, silent: true)
116
137
  end
117
138
 
@@ -160,6 +181,10 @@ module SvelteOnRails
160
181
  valid_display = valid_options.map { |opt| opt.gsub(/^--/, '') }.join(', ')
161
182
  raise Thor::Error, "Unknown options: #{unknown_options.join(', ')}. Valid options are: #{valid_display}\nNothing done."
162
183
  end
184
+
185
+ if options[:turbo_streams] && !(options[:full] || options[:turbo])
186
+ raise Thor::Error, "--turbo-streams option cannot be used without --turbo"
187
+ end
163
188
  end
164
189
 
165
190
  def application_js_path
@@ -1,9 +1,12 @@
1
1
  require "svelte_on_rails/configuration"
2
2
  require "svelte_on_rails/view_helpers"
3
+ require "svelte_on_rails/turbo_stream"
4
+ require "svelte_on_rails/railtie" if defined?(Rails)
5
+
3
6
  require "svelte_on_rails/renderer/renderer"
7
+
4
8
  require "svelte_on_rails/lib/utils"
5
9
  require "svelte_on_rails/lib/view_helper_support"
6
- require "svelte_on_rails/railtie" if defined?(Rails)
7
10
 
8
11
  # installer
9
12
  require 'svelte_on_rails/installer/utils'
@@ -26,7 +26,7 @@ module SvelteOnRails
26
26
  if stderr.present?
27
27
  raise stderr
28
28
  else
29
- puts "Installed #{gem_name} version #{check_gem_version(gem_name)}"
29
+ puts "Successfully installed #{gem_name} version #{check_gem_version(gem_name)}"
30
30
  end
31
31
  end
32
32
  end
@@ -37,6 +37,7 @@ module SvelteOnRails
37
37
 
38
38
  end
39
39
 
40
+
40
41
  def self.remove_hello_world(templates = ['rails_vite_hello_world'], app_root: nil, ask: true)
41
42
 
42
43
  utils = SvelteOnRails::Installer::Utils
@@ -133,15 +133,26 @@ module SvelteOnRails
133
133
  end
134
134
  end
135
135
 
136
- def self.run_command(command)
136
+ def self.run_command(command, success_message: false)
137
137
 
138
138
  Dir.chdir(Rails.root) do
139
- stdout, stderr, status = Open3.capture3(command)
140
- if stderr.present?
141
- puts "Error running command «#{command}»:"
142
- raise stderr
143
- else
144
- puts "#{command} => Success"
139
+ Bundler.with_unbundled_env do
140
+ `pwd`
141
+ stdout, stderr, status = Open3.capture3(command)
142
+ err_msg = if stderr.present?
143
+ stderr.strip
144
+ elsif success_message && !stdout.match(/#{success_message}/)
145
+ "missing string «#{success_message}» on result:\n\n+++#{stdout}\n+++"
146
+ else
147
+ end
148
+
149
+ if err_msg
150
+ puts "Error running command «#{command}»:"
151
+ raise err_msg
152
+ else
153
+ puts "#{command} => Success"
154
+ end
155
+
145
156
  end
146
157
  end
147
158
 
@@ -179,11 +190,12 @@ module SvelteOnRails
179
190
 
180
191
  if existing.present? && ask_for_overwrite
181
192
  begin
182
- puts "#{'File'.pluralize(existing.length)} already exists:\n#{existing.map { |p| p[1] }.join("\n")}.\nOverwrite? (y/n)"
193
+ puts "#{'File'.pluralize(existing.length)} already exists:\n#{existing.map { |p| p[1] }.join("\n")}.\nOverwrite? (y/n)
194
+ "
183
195
  continue = STDIN.gets.chomp.downcase[0]
184
196
  end until ['y', 'n'].include?(continue)
185
197
  if continue == 'n'
186
- puts "Skipping write #{'template'.pluralize(templates.length)}."
198
+ puts " Skipping write #{'template'.pluralize(templates.length)}."
187
199
  return
188
200
  end
189
201
  end
@@ -2,18 +2,25 @@ import {loadComponentModule, readPropsFromStdin} from './utils.js';
2
2
 
3
3
  (async () => {
4
4
 
5
+ console.log(`[svelte-on-rails:debug] awaiting load component => «${process.argv[2]}»`)
6
+
5
7
  const MyComponent = await loadComponentModule(process.argv[2]);
8
+ console.log(`[svelte-on-rails:debug] component read: «${MyComponent}}»`)
9
+
6
10
  const props = await readPropsFromStdin();
7
- const payload = {out: ''};
11
+ console.log(`[svelte-on-rails:debug] props read: «${props}»`)
12
+
13
+ const payload = {out: []};
8
14
 
9
15
  try {
10
16
  MyComponent(payload, props); // Writes directly to payload.out
17
+ console.log(`[svelte-on-rails:debug] written to payload`)
11
18
  } catch (error) {
12
- console.error('Error rendering component:', error);
19
+ console.error('[svelte-on-rails:debug] Error rendering component:', error);
13
20
  process.exit(1);
14
21
  }
15
22
 
16
- const res = {status: 'SUCCESS', html: payload.out};
17
- console.log(JSON.stringify(res));
23
+ const res = {status: 'SUCCESS', html: payload.out.join('')};
24
+ console.log('[svelte-on-rails:successful-json-response]' + JSON.stringify(res));
18
25
  })();
19
26
 
@@ -32,10 +32,19 @@ module SvelteOnRails
32
32
  ].join(' ')
33
33
 
34
34
  Dir.chdir(cnf.rails_root) do
35
- stdout, stderr, status = Open3.capture3(cmd, stdin_data: props.to_json, chdir: cnf.rails_root)
35
+ stdout, stderr, status = Open3.capture3(cmd, stdin_data: props.to_json)
36
+
37
+ ary = stdout.split('[svelte-on-rails:successful-json-response]')
38
+
39
+ unless ary.length == 2
40
+ raise "[svelte-on-rails] render ERROR for component: #{@component_files[:svelte_filename]}\n\ncommand:\n+++\n#{cmd}\n+++\n\nstdout:\n+++\n#{stdout}+++\n\n\nstderr:\n+++\n#{stderr}+++"
41
+ end
42
+
36
43
 
37
44
  begin
38
- res = JSON.parse(stdout)
45
+
46
+
47
+ res = JSON.parse(ary[1])
39
48
  css_file = @component_files[:compiled_file] + '.css'
40
49
  if File.exist?(css_file)
41
50
  res['css'] = File.read(css_file)
@@ -50,7 +59,7 @@ module SvelteOnRails
50
59
  return res
51
60
  rescue JSON::ParserError => e
52
61
 
53
- raise "[svelte-on-rails] render ERROR Svelte Server-side: Expected JSON, got: «#{stdout}»\n\ncomponent: #{@component_files[:svelte_filename]}\n\nstdout:\n+++\n#{stderr}+++\n\ncmd: «#{cmd}»"
62
+ raise "[svelte-on-rails] render ERROR Svelte Server-side for component: #{@component_files[:svelte_filename]}\n\nError message:\n+++\n#{e.message}\n+++\n\nstdout:\n+++\n#{stdout}+++\n\n\nstderr:\n+++\n#{stderr}+++"
54
63
  end
55
64
  end
56
65
  end
@@ -0,0 +1,43 @@
1
+ module SvelteOnRails
2
+ class TurboStream
3
+ def dispatch_event(event: 'stream-action', event_detail: nil, selector: nil, component: nil, stream_name: nil)
4
+
5
+ args = {
6
+ eventDetail: event_detail,
7
+ component: component,
8
+ event: event,
9
+ selector: selector
10
+ }
11
+
12
+ args_enc = Base64.strict_encode64(args.to_json)
13
+
14
+ Turbo::StreamsChannel.send(
15
+ "broadcast_append_to",
16
+ stream_name || configs['stream_name'],
17
+ target: configs['target_html_id'],
18
+ content: "<div style=\"display: none;\" data-controller=\"svelte-on-rails-turbo-stream\" data-args=\"#{args_enc}\"></div>"
19
+ )
20
+
21
+ end
22
+
23
+ private
24
+
25
+ def configs
26
+ @configs ||= begin
27
+
28
+ conf = SvelteOnRails::Configuration.instance
29
+ unless conf.configs[:turbo_stream]
30
+ raise '[svelte-on-rails] missing configuration: :turbo_stream'
31
+ end
32
+ unless conf.configs[:turbo_stream]['target_html_id']
33
+ raise '[svelte-on-rails] missing configuration: turbo_stream/target_html_id'
34
+ end
35
+ unless conf.configs[:turbo_stream]['stream_name']
36
+ raise '[svelte-on-rails] missing configuration: turbo_stream/stream_name'
37
+ end
38
+
39
+ conf.configs[:turbo_stream]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -21,6 +21,12 @@ non_ssr_request_header: 'X-Turbo-Request-ID'
21
21
  # expires_in: 90.minutes (=> default / fallback: 1 hour)
22
22
  # namespace: 'my-app-svelte-on-rails'
23
23
 
24
+ turbo_stream:
25
+ # this part you need when you want to be able to trigger javascript actions on svelte-components from the backend
26
+ target_html_id: 'svelte-on-rails-stream-actions-box'
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'
29
+
24
30
  development:
25
31
  watch_changes: true
26
32
  # Check on every request if any file within the svelte components folder have changed, for recompiling
@@ -3,4 +3,23 @@ class SvelteOnRailsHelloWorldController < ApplicationController
3
3
  def index
4
4
  end
5
5
 
6
+ def turbo_stream_action
7
+
8
+ if params['increase']
9
+ SvelteOnRails::TurboStream.new.dispatch_event(
10
+ event: 'click',
11
+ selector: '.counter-button',
12
+ component: '/javascript/components/TurboStreamsChannel'
13
+ )
14
+ render plain: 'increase-action streamed'
15
+ else
16
+ SvelteOnRails::TurboStream.new.dispatch_event(
17
+ event_detail: { message: "Special Chars from the server: äöü🤣🌴🌍漢字", user: "Müller" }
18
+ )
19
+ render plain: 'component-action streamed'
20
+ end
21
+
22
+ head :ok
23
+ end
24
+
6
25
  end
@@ -53,7 +53,7 @@
53
53
  -webkit-box-shadow: 2px 3px 16px -1px rgba(0, 0, 0, 0.75);
54
54
  -moz-box-shadow: 2px 3px 16px -1px rgba(0, 0, 0, 0.75);
55
55
  }
56
- img, .wrap-svg {
56
+ img {
57
57
  display: inline-block;
58
58
  width: 30px;
59
59
  height: 30px;
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import axios from "axios";
3
+ import {addComponentStreamListener} from '@csedl/svelte-on-rails/src/componentStreamListener'
4
+ import { onMount } from "svelte";
5
+
6
+ let counter = $state(0)
7
+ let results = $state([])
8
+ let incrBtn
9
+
10
+
11
+ onMount(() => {
12
+ incrBtn.addEventListener('click', increaseCounter)
13
+ });
14
+
15
+ function callChannelAction(params) {
16
+ results = []
17
+ axios.get(`/svelte_on_rails_hello_world/turbo_stream_action?${params}`)
18
+ .then(function (response) {
19
+ results.push(
20
+ {
21
+ text: `server action called, status: ${response.status}`,
22
+ class: 'called-for-action'
23
+ })
24
+ })
25
+ }
26
+
27
+ function increaseCounter() {
28
+ counter += 1
29
+ }
30
+
31
+ const handleCableEvent = (ev) => {
32
+ results.push(
33
+ {
34
+ text: `Message received from TurboStream: ${JSON.stringify(ev.detail.message)}`,
35
+ class: 'stream-action-received'
36
+ }
37
+ )
38
+ };
39
+
40
+ </script>
41
+
42
+ <h1 use:addComponentStreamListener={handleCableEvent}>Test TurboStreams Channel</h1>
43
+
44
+ <p>Actions that are triggered by SvelteOnRails::TurboStream channel from the server</p>
45
+
46
+ <button onstream-action="{() => callChannelAction('increase=true')}">Call increase action over Channel</button>
47
+
48
+ <button bind:this={incrBtn} class="counter-button" onclick="{increaseCounter}">increase {counter}</button>
49
+
50
+ <button class="call-channel-action" onclick="{callChannelAction}">Action</button>
51
+
52
+ <ul class="results">
53
+ {#each results as result}
54
+ <li class="{result.class}">{result.text}</li>
55
+ {/each}
56
+ </ul>
@@ -4,6 +4,8 @@
4
4
  <%= link_to 'Backend/Frontend Test', '/svelte_on_rails_hello_world/backend_frontend_rendered' %>
5
5
  |
6
6
  <%= link_to 'SSR-Auto rendered (default)', '/svelte_on_rails_hello_world/ssr_auto_rendered' %>
7
+ |
8
+ <%= link_to 'Turbo Streams', '/svelte_on_rails_hello_world/turbo_streams_channel' %>
7
9
  </div>
8
10
 
9
11
  <% turbo_id = request.headers['X-Turbo-Request-ID'] %>
@@ -13,4 +13,14 @@
13
13
  width: 32px;
14
14
  height: 32px;
15
15
  }
16
+ .svelte-component {
17
+ border: 1px solid lightgray;
18
+ max-width: 30rem;
19
+ padding: 2rem;
20
+ margin: 2rem;
21
+ }
22
+
23
+ button {
24
+ margin: 4px;
25
+ }
16
26
  </style>
@@ -0,0 +1,12 @@
1
+ <%= turbo_stream_from 'public' %>
2
+
3
+ <%= render 'styles' %>
4
+
5
+
6
+ <%= render 'nav' %>
7
+
8
+
9
+ <%= svelte_component "TurboStreamsChannel" %>
10
+
11
+ <%= content_tag :div, id: 'svelte-on-rails-stream-actions-box' do %>
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: 4.1.1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Sedlmair
@@ -47,6 +47,7 @@ files:
47
47
  - lib/svelte_on_rails/renderer/render.js
48
48
  - lib/svelte_on_rails/renderer/renderer.rb
49
49
  - lib/svelte_on_rails/renderer/utils.js
50
+ - lib/svelte_on_rails/turbo_stream.rb
50
51
  - lib/svelte_on_rails/view_helpers.rb
51
52
  - lib/tasks/svelte_on_rails_tasks.rake
52
53
  - templates/config_base/app/frontend/ssr/ssr.js
@@ -62,6 +63,7 @@ files:
62
63
  - templates/rails_vite_hello_world/app/frontend/javascript/components/PngImport.svelte
63
64
  - templates/rails_vite_hello_world/app/frontend/javascript/components/SvelteOnRailsHelloWorld.svelte
64
65
  - templates/rails_vite_hello_world/app/frontend/javascript/components/SvgRawImport.svelte
66
+ - templates/rails_vite_hello_world/app/frontend/javascript/components/TurboStreamsChannel.svelte
65
67
  - templates/rails_vite_hello_world/app/frontend/javascript/components/sub/NestedComponent.svelte
66
68
  - templates/rails_vite_hello_world/app/frontend/javascript/nestedJavascript.js
67
69
  - templates/rails_vite_hello_world/app/frontend/javascript/nestedJavascriptToggled.js
@@ -70,6 +72,7 @@ files:
70
72
  - templates/rails_vite_hello_world/app/views/svelte_on_rails_hello_world/backend_frontend_rendered.html.erb
71
73
  - templates/rails_vite_hello_world/app/views/svelte_on_rails_hello_world/index.html.erb
72
74
  - templates/rails_vite_hello_world/app/views/svelte_on_rails_hello_world/ssr_auto_rendered.html.erb
75
+ - templates/rails_vite_hello_world/app/views/svelte_on_rails_hello_world/turbo_streams_channel.html.erb
73
76
  homepage: https://gitlab.com/sedl/svelte-on-rails
74
77
  licenses:
75
78
  - MIT