pageflow 15.4.0 → 15.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pageflow might be problematic. Click here for more details.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -166
  3. data/admins/pageflow/user.rb +0 -2
  4. data/app/assets/javascripts/pageflow/dist/ui.js +32 -9
  5. data/app/assets/javascripts/pageflow/editor/vendor.js +1 -0
  6. data/app/assets/stylesheets/pageflow/themes/default/page.scss +7 -0
  7. data/app/models/pageflow/chapter.rb +3 -9
  8. data/app/models/pageflow/page.rb +1 -4
  9. data/app/models/pageflow/revision.rb +0 -4
  10. data/app/models/pageflow/storyline.rb +2 -9
  11. data/app/views/pageflow/admin/initial_passwords/edit.html.erb +2 -1
  12. data/app/views/pageflow/themes/_theme.json.jbuilder +1 -1
  13. data/config/initializers/revision_components.rb +5 -0
  14. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +37 -13
  15. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +19 -6
  16. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +28 -0
  17. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +3 -9
  18. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +1 -4
  19. data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +3 -9
  20. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -9
  21. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/_global_notices.html.erb +10 -0
  22. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +6 -3
  23. data/entry_types/scrolled/config/locales/de.yml +14 -0
  24. data/entry_types/scrolled/config/locales/en.yml +15 -49
  25. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +43 -6
  26. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -0
  27. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/create_bundle_symlinks_for_yarn.rake +32 -0
  28. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/dummy.rake +8 -0
  29. data/entry_types/scrolled/lib/tasks/{pageflow_scrolled_tasks.rake → pageflow_scrolled/storybook.rake} +53 -14
  30. data/entry_types/scrolled/package/contentElements-editor.js +66 -7
  31. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  32. data/entry_types/scrolled/package/contentElements-frontend.js +109 -52
  33. data/entry_types/scrolled/package/editor.js +34 -25
  34. data/entry_types/scrolled/package/frontend/EditableText-7093fd0e.js +1071 -0
  35. data/entry_types/scrolled/package/frontend/Viewer-e49e7807.js +387 -0
  36. data/entry_types/scrolled/package/frontend/{Wavesurfer-b88b02e0.js → Wavesurfer-0adf5667.js} +1 -1
  37. data/entry_types/scrolled/package/frontend/{components-3ead1b4a.js → components-6a6793ca.js} +2 -1
  38. data/entry_types/scrolled/package/frontend/i18n-4dc6c377.js +1092 -0
  39. data/entry_types/scrolled/package/frontend/index.css +2 -2
  40. data/entry_types/scrolled/package/frontend/index.js +358 -179
  41. data/entry_types/scrolled/package/frontend/useBrowserFeature-91a4c29d.js +33 -0
  42. data/entry_types/scrolled/package/package.json +3 -5
  43. data/lib/generators/pageflow/initializer/templates/pageflow.rb +0 -7
  44. data/lib/pageflow/entry_export_import/revision_serialization.rb +15 -13
  45. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +18 -26
  46. data/lib/pageflow/entry_type_configuration.rb +1 -0
  47. data/lib/pageflow/nested_revision_component.rb +49 -0
  48. data/lib/pageflow/revision_component.rb +6 -2
  49. data/lib/pageflow/user_mixin.rb +2 -1
  50. data/lib/pageflow/version.rb +1 -1
  51. data/package/editor.js +2 -1
  52. data/package/frontend.js +13 -2
  53. data/package/ui.js +32 -9
  54. data/spec/factories/test_revision_components.rb +4 -0
  55. metadata +18 -10
  56. data/entry_types/scrolled/package/frontend/EditableText-43c50894.js +0 -2161
@@ -6,17 +6,39 @@ module PageflowScrolled
6
6
 
7
7
  source_root File.expand_path('templates', __dir__)
8
8
 
9
- def install_webpacker
10
- require 'webpacker'
11
- gemfile = File.expand_path('../../../../../../Gemfile', __dir__)
12
- rake "webpacker:install BUNDLE_GEMFILE=#{gemfile}"
9
+ def initializer
10
+ inject_into_file('config/initializers/pageflow.rb',
11
+ after: "Pageflow.configure do |config|\n") do
12
+ " config.plugin(PageflowScrolled.plugin)\n\n" \
13
+ " config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|\n" \
14
+ " entry_type_config.plugin(ScrolledThemesPlugin.new)\n" \
15
+ " end\n\n"
16
+ end
17
+ end
18
+
19
+ def theme_plugin
20
+ # Ruby files in the lib directory are eager loaded in
21
+ # production. This includes template files in
22
+ # lib/generators. Template file extension (.tt) is removed by
23
+ # Thor automatically and ensures the file is not picked up by
24
+ # eager loading.
25
+ template 'themes_plugin.rb.tt', 'app/plugins/scrolled_themes_plugin.rb'
26
+ end
27
+
28
+ def install_packages
29
+ run 'yarn add postcss-url@^8.0.0 @fontsource/source-sans-pro'
13
30
  end
14
31
 
15
32
  def webpack_environment
16
33
  inject_into_file('config/webpack/environment.js',
17
34
  before: "module.exports = environment\n") do
18
- "const pageflowConfig = require('pageflow/config/webpack')\n" \
19
- "environment.config.merge(pageflowConfig)\n\n"
35
+ "environment.config.merge(require('pageflow/config/webpack'))\n" \
36
+ "environment.config.merge(require('pageflow-scrolled/config/webpack'))\n\n" \
37
+ "// Opt into future default behavior of Webpacker [1] to work around\n" \
38
+ "// problems with Video.js DASH service worker.\n" \
39
+ "//\n" \
40
+ "// [1] https://github.com/rails/webpacker/pull/2624\n" \
41
+ "environment.loaders.delete('nodeModules')\n\n"
20
42
  end
21
43
  end
22
44
 
@@ -31,6 +53,14 @@ module PageflowScrolled
31
53
  end
32
54
  end
33
55
 
56
+ def postcss_config
57
+ inject_into_file('postcss.config.js',
58
+ after: "require('postcss-import'),\n") do
59
+ " // Make relative urls in fontsource packages work\n" \
60
+ " require('postcss-url')({url: 'rebase'}),\n"
61
+ end
62
+ end
63
+
34
64
  def editor_pack
35
65
  create_file 'app/javascript/packs/pageflow-scrolled-editor.js', <<-JS
36
66
  import 'pageflow-scrolled/editor';
@@ -62,6 +92,13 @@ module PageflowScrolled
62
92
  JS
63
93
  end
64
94
 
95
+ def default_font_pack
96
+ create_file 'app/javascript/packs/fonts/sourceSansPro.css', <<-CSS
97
+ @import "@fontsource/source-sans-pro/400.css";
98
+ @import "@fontsource/source-sans-pro/700.css";
99
+ CSS
100
+ end
101
+
65
102
  def default_theme
66
103
  directory 'theme', 'app/javascript/pageflow-scrolled/themes/default'
67
104
  end
@@ -0,0 +1,26 @@
1
+ # Extracted from initializer to allow auto loading changes in
2
+ # development
3
+ class ScrolledThemesPlugin
4
+ def configure(config) # rubocop:disable Metrics/MethodLength
5
+ config.themes.register(:default,
6
+ stylesheet_packs: ['fonts/sourceSansPro'],
7
+ font_family: {
8
+ entry: '"Source Sans Pro", sans-serif',
9
+ navigation: '"Source Sans Pro", sans-serif'
10
+ },
11
+ colors: {
12
+ accent: '#e10028',
13
+ navigation: {
14
+ surface: '#fff',
15
+ on_surface: '#000',
16
+ primary_on_surface: '#00375a',
17
+ secondary_on_surface: '#c2c2c2',
18
+ background: 'rgba(255, 255, 255, 0.95)',
19
+ on_background: '#000',
20
+ primary_on_background: '#00375a'
21
+ }
22
+ },
23
+ logo_alt_text: 'Pageflow',
24
+ theme_color: '#ffffff')
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ namespace :pageflow_scrolled do
2
+ desc <<-DESC
3
+ Make Yarn use packages embedded in gems.
4
+
5
+ For each package.json dependency of the form
6
+
7
+ .bundle/for-yarn/gem-name/package/path
8
+
9
+ create a symlink in the Git ignored directory .bundle/for-yarn which
10
+ points to the location of the gem as reported by `bundle show`.
11
+
12
+ This script is executed as preinstall script when running `yarn
13
+ install`.
14
+ DESC
15
+ task :create_bundle_symlinks_for_yarn do
16
+ referenced_gems =
17
+ File.read('package.json').scan(%r{.bundle/for-yarn/([a-z_-]+)}).flatten.uniq
18
+
19
+ FileUtils.rm_rf '.bundle/for-yarn'
20
+ FileUtils.mkdir_p '.bundle/for-yarn'
21
+
22
+ puts 'Creating symlinks for .bundle entries in package.json:'
23
+
24
+ referenced_gems.each do |gem|
25
+ symlink = ".bundle/for-yarn/#{gem}"
26
+ gem_location = `bundle show #{gem}`.strip
27
+
28
+ puts "#{symlink} -> #{gem_location}"
29
+ FileUtils.ln_s gem_location, symlink
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ namespace :pageflow_scrolled do
2
+ desc 'Generate dummy app for current Rails version.'
3
+ task :dummy do
4
+ require 'pageflow/support'
5
+ ENV['PAGEFLOW_INSTALL_WEBPACKER'] = 'true'
6
+ Pageflow::Dummy.setup
7
+ end
8
+ end
@@ -1,14 +1,9 @@
1
1
  namespace :pageflow_scrolled do
2
- desc 'Generate dummy app for current Rails version.'
3
- task :dummy do
4
- require 'pageflow/support'
5
- Pageflow::Dummy.setup
6
- end
7
-
8
2
  namespace :storybook do
9
3
  namespace :seed do
10
- desc 'Recreate storybook entry and set up storybook JSON seed from it'
11
- task :setup, [:output] => [:destroy_entry, :create_entry, :generate_json]
4
+ desc 'Recreate storybook entry and set up storybook JSON seed/preview-head.html from it'
5
+ task :setup, [:output_dir] => [:destroy_entry, :create_entry,
6
+ :generate_json, :generate_head_html]
12
7
 
13
8
  desc 'Destroy entry to generate Storybook entry JSON seed from'
14
9
  task destroy_entry: :environment do
@@ -66,6 +61,20 @@ namespace :pageflow_scrolled do
66
61
  configuration: {
67
62
  testReferenceName: 'churchBefore'
68
63
  }
64
+ }.stringify_keys,
65
+ equirectangularMono: {
66
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/equirectangular_mono.jpg',
67
+ configuration: {
68
+ testReferenceName: 'equirectangularMono',
69
+ projection: 'equirectangular_mono'
70
+ }
71
+ }.stringify_keys,
72
+ equirectangularStereo: {
73
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/equirectangular_stereo.png',
74
+ configuration: {
75
+ testReferenceName: 'equirectangularStereo',
76
+ projection: 'equirectangular_stereo'
77
+ }
69
78
  }.stringify_keys
70
79
  },
71
80
  video_files: {
@@ -101,7 +110,7 @@ namespace :pageflow_scrolled do
101
110
  end
102
111
 
103
112
  desc 'Generate Storybook entry JSON seed'
104
- task :generate_json, [:output] => :environment do |_t, args|
113
+ task :generate_json, [:output_dir] => :environment do |_t, args|
105
114
  entry = Pageflow::Entry.find_by_title('Storybook seed')
106
115
 
107
116
  unless entry
@@ -109,6 +118,12 @@ namespace :pageflow_scrolled do
109
118
  exit 1
110
119
  end
111
120
 
121
+ if args[:output_dir].blank?
122
+ puts 'Missing argument: Pass output directory via '\
123
+ '`rake pageflow_scrolled:storybook:seed:setup[some/directory]`'
124
+ exit 1
125
+ end
126
+
112
127
  draft_entry = Pageflow::DraftEntry.new(entry)
113
128
 
114
129
  seed =
@@ -120,14 +135,38 @@ namespace :pageflow_scrolled do
120
135
  locals: {entry: draft_entry})
121
136
  end
122
137
 
123
- if args[:output].blank?
124
- puts 'Missing argument: Pass output path via '\
125
- '`rake pageflow_scrolled:storybook:seed:setup[some/path/seed.json]`'
138
+ output = File.join(args[:output_dir], 'seed.json')
139
+ File.write(output, seed)
140
+ puts "Wrote #{output}"
141
+ end
142
+
143
+ desc 'Generate Storybook preview-head.html'
144
+ task :generate_head_html, [:output_dir] => :environment do |_t, args|
145
+ entry = Pageflow::Entry.find_by_title('Storybook seed')
146
+
147
+ unless entry
148
+ puts 'Seed entry does not exist. Run pageflow_scrolled:storybook:seed:create_entry first.'
126
149
  exit 1
127
150
  end
128
151
 
129
- File.write(args[:output], seed)
130
- puts "Wrote #{args[:output]}"
152
+ if args[:output_dir].blank?
153
+ puts 'Missing argument: Pass output directory via '\
154
+ '`rake pageflow_scrolled:storybook:seed:setup[some/directory]`'
155
+ exit 1
156
+ end
157
+
158
+ draft_entry = Pageflow::DraftEntry.new(entry)
159
+
160
+ html =
161
+ File.read(File.join(__dir__, '..', '..', '..', 'package', '.storybook',
162
+ 'preview-head.html.template')) +
163
+ PageflowScrolled::EntriesController.render(inline: <<-ERB, locals: {entry: draft_entry})
164
+ <%= scrolled_theme_properties_style_tag(entry.theme) %>
165
+ ERB
166
+
167
+ output = File.join(args[:output_dir], 'preview-head.html')
168
+ File.write(output, html)
169
+ puts "Wrote #{output}"
131
170
  end
132
171
  end
133
172
  end
@@ -1,5 +1,5 @@
1
1
  import { editor, NoOptionsHintView, buttonStyles } from 'pageflow-scrolled/editor';
2
- import { FileInputView, CheckBoxInputView, ColorInputView as ColorInputView$1, editor as editor$1, transientReferences, ListView } from 'pageflow/editor';
2
+ import { FileInputView, CheckBoxInputView, ColorInputView as ColorInputView$1, editor as editor$1, transientReferences, ListView, SliderInputView as SliderInputView$1, SelectInputView as SelectInputView$1, EnumTableCellView } from 'pageflow/editor';
3
3
  import { SelectInputView, ColorInputView, TextInputView, SliderInputView, CheckBoxInputView as CheckBoxInputView$1, UrlInputView, ConfigurationEditorView, cssModulesUtils } from 'pageflow/ui';
4
4
  import Marionette from 'backbone.marionette';
5
5
  import I18n from 'i18n-js';
@@ -7,10 +7,13 @@ import Backbone from 'backbone';
7
7
  import _ from 'underscore';
8
8
 
9
9
  editor.contentElementTypes.register('heading', {
10
- supportedPositions: ['inline'],
10
+ supportedPositions: ['inline', 'wide'],
11
+ defaultConfig: {
12
+ position: 'wide'
13
+ },
11
14
  configurationEditor: function configurationEditor() {
12
15
  this.tab('general', function () {
13
- this.view(NoOptionsHintView);
16
+ this.group('ContentElementPosition');
14
17
  });
15
18
  }
16
19
  });
@@ -101,6 +104,7 @@ editor.contentElementTypes.register('textBlock', {
101
104
  });
102
105
 
103
106
  editor.contentElementTypes.register('inlineImage', {
107
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'wide', 'full'],
104
108
  configurationEditor: function configurationEditor() {
105
109
  this.tab('general', function () {
106
110
  this.input('id', FileInputView, {
@@ -115,6 +119,7 @@ editor.contentElementTypes.register('inlineImage', {
115
119
  });
116
120
 
117
121
  editor.contentElementTypes.register('inlineVideo', {
122
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
118
123
  configurationEditor: function configurationEditor() {
119
124
  this.tab('general', function () {
120
125
  this.input('id', FileInputView, {
@@ -139,7 +144,9 @@ editor.contentElementTypes.register('inlineVideo', {
139
144
  });
140
145
 
141
146
  editor.contentElementTypes.register('inlineAudio', {
142
- configurationEditor: function configurationEditor() {
147
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
148
+ configurationEditor: function configurationEditor(_ref) {
149
+ var entry = _ref.entry;
143
150
  this.tab('general', function () {
144
151
  this.input('id', FileInputView, {
145
152
  collection: 'audio_files',
@@ -160,7 +167,7 @@ editor.contentElementTypes.register('inlineAudio', {
160
167
  this.input('waveformColor', ColorInputView, {
161
168
  visibleBinding: 'playerControlVariant',
162
169
  visibleBindingValue: 'waveform',
163
- defaultValue: '#e10028'
170
+ defaultValue: entry.getTheme().get('options').colors.accent
164
171
  });
165
172
  this.input('atmoDuringPlayback', SelectInputView, {
166
173
  values: ['play', 'mute', 'turnDown']
@@ -172,6 +179,7 @@ editor.contentElementTypes.register('inlineAudio', {
172
179
  });
173
180
 
174
181
  editor.contentElementTypes.register('inlineBeforeAfter', {
182
+ supportedPositions: ['inline'],
175
183
  configurationEditor: function configurationEditor() {
176
184
  this.tab('general', function () {
177
185
  this.input('before_id', FileInputView, {
@@ -214,11 +222,12 @@ editor.contentElementTypes.register('soundDisclaimer', {
214
222
  });
215
223
 
216
224
  editor.contentElementTypes.register('videoEmbed', {
225
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
217
226
  configurationEditor: function configurationEditor() {
218
227
  this.tab('general', function () {
219
228
  this.input('videoSource', UrlInputView, {
220
229
  supportedHosts: ['http://youtu.be', 'https://youtu.be', 'http://www.youtube.com', 'https://www.youtube.com', 'http://vimeo.com', 'https://vimeo.com', 'http://www.facebook.com', 'https://www.facebook.com'],
221
- displayPropertyName: 'videoSource',
230
+ displayPropertyName: 'displayVideoSource',
222
231
  required: true,
223
232
  permitHttps: true
224
233
  });
@@ -427,6 +436,7 @@ editor.registerSideBarRouting({
427
436
  }); // register external link list content element configuration editor for sidebar
428
437
 
429
438
  editor.contentElementTypes.register('externalLinkList', {
439
+ supportedPositions: ['inline'],
430
440
  configurationEditor: function configurationEditor(_ref) {
431
441
  var entry = _ref.entry;
432
442
  this.tab('general', function () {
@@ -460,11 +470,12 @@ var DatawrapperAdView = Marionette.ItemView.extend({
460
470
  });
461
471
 
462
472
  editor.contentElementTypes.register('dataWrapperChart', {
473
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
463
474
  configurationEditor: function configurationEditor() {
464
475
  this.tab('general', function () {
465
476
  this.input('url', UrlInputView, {
466
477
  supportedHosts: ['http://cf.datawrapper.de', 'https://cf.datawrapper.de', 'http://datawrapper.dwcdn.de', 'https://datawrapper.dwcdn.de', 'http://datawrapper.dwcdn.net', 'https://datawrapper.dwcdn.net', 'http://charts.datawrapper.de', 'https://charts.datawrapper.de'],
467
- displayPropertyName: 'url',
478
+ displayPropertyName: 'displayUrl',
468
479
  required: true,
469
480
  permitHttps: true
470
481
  });
@@ -480,3 +491,51 @@ editor.contentElementTypes.register('dataWrapperChart', {
480
491
  });
481
492
  }
482
493
  });
494
+
495
+ editor.contentElementTypes.register('vrImage', {
496
+ configurationEditor: function configurationEditor() {
497
+ this.tab('general', function () {
498
+ this.input('image', FileInputView, {
499
+ collection: 'image_files',
500
+ fileSelectionHandler: 'contentElementConfiguration',
501
+ filter: 'with_projection',
502
+ positioning: false
503
+ });
504
+ this.input('initialYaw', SliderInputView$1, {
505
+ unit: '°',
506
+ minValue: -180,
507
+ maxValue: 180
508
+ });
509
+ this.input('initialPitch', SliderInputView$1, {
510
+ unit: '°',
511
+ minValue: -60,
512
+ maxValue: 60
513
+ });
514
+ this.group('ContentElementCaption');
515
+ this.group('ContentElementPosition');
516
+ });
517
+ }
518
+ });
519
+ editor.fileTypes.modify('image_files', {
520
+ configurationEditorInputs: function configurationEditorInputs(model) {
521
+ var values = ['equirectangular_mono', 'equirectangular_stereo'];
522
+ return [{
523
+ name: 'projection',
524
+ inputView: SelectInputView$1,
525
+ inputViewOptions: {
526
+ includeBlank: true,
527
+ values: values
528
+ }
529
+ }];
530
+ },
531
+ confirmUploadTableColumns: [{
532
+ name: 'projection',
533
+ cellView: EnumTableCellView
534
+ }],
535
+ filters: [{
536
+ name: 'with_projection',
537
+ matches: function matches(file) {
538
+ return !!file.configuration.get('projection');
539
+ }
540
+ }]
541
+ });
@@ -1 +1 @@
1
- .Heading-module_root__33TFw{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;margin-top:.2em;margin-bottom:0;padding-top:.3em}@media (orientation:landscape){.Heading-module_first__1PMJX{padding-top:25%}}.BeforeAfter-module_sliderStart__2C5cN{background-color:#fff;position:absolute;z-index:1}.BeforeAfter-module_container__2Lm06{height:100%;--frame1pos:-8;--frame2pos:16;--frame3pos:-32;--frame4pos:32;--frame1px:calc(var(--frame1pos)*1px);--frame2px:calc(var(--frame2pos)*1px);--frame3px:calc(var(--frame3pos)*1px);--frame4px:calc(var(--frame4pos)*1px)}.BeforeAfter-module_container__2Lm06>div{height:100%!important}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe div div:nth-child(3){-webkit-animation:BeforeAfter-module_SliderLeftRightShake__2mcn5 1.5s cubic-bezier(.36,.07,.19,.97) both;animation:BeforeAfter-module_SliderLeftRightShake__2mcn5 1.5s cubic-bezier(.36,.07,.19,.97) both}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe div img:nth-child(2){-webkit-animation:BeforeAfter-module_BeforeImageLeftRightShake__38m9V 1.5s cubic-bezier(.36,.07,.19,.97) both;animation:BeforeAfter-module_BeforeImageLeftRightShake__38m9V 1.5s cubic-bezier(.36,.07,.19,.97) both}.BeforeAfter-module_container__2Lm06 div div:nth-child(4) div{transition:opacity .1s ease-out .3s!important}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe div img:first-child{-webkit-animation:BeforeAfter-module_AfterImageLeftRightShake__3WMf1 1.5s cubic-bezier(.36,.07,.19,.97) both;animation:BeforeAfter-module_AfterImageLeftRightShake__3WMf1 1.5s cubic-bezier(.36,.07,.19,.97) both}.BeforeAfter-module_container__2Lm06 div div:nth-child(5) div{transition:opacity .1s ease-out .3s!important}@-webkit-keyframes BeforeAfter-module_BeforeImageLeftRightShake__38m9V{10%,to{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame1px)),auto,auto)}20%,80%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame2px)),auto,auto)}30%,50%,70%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame3px)),auto,auto)}40%,60%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame4px)),auto,auto)}}@keyframes BeforeAfter-module_BeforeImageLeftRightShake__38m9V{10%,to{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame1px)),auto,auto)}20%,80%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame2px)),auto,auto)}30%,50%,70%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame3px)),auto,auto)}40%,60%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame4px)),auto,auto)}}@-webkit-keyframes BeforeAfter-module_AfterImageLeftRightShake__3WMf1{10%,to{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame1px)))}20%,80%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame2px)))}30%,50%,70%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame3px)))}40%,60%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame4px)))}}@keyframes BeforeAfter-module_AfterImageLeftRightShake__3WMf1{10%,to{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame1px)))}20%,80%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame2px)))}30%,50%,70%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame3px)))}40%,60%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame4px)))}}@-webkit-keyframes BeforeAfter-module_SliderLeftRightShake__2mcn5{10%,to{transform:translate3d(-20%,0,0)}20%,80%{transform:translate3d(40%,0,0)}30%,50%,70%{transform:translate3d(-80%,0,0)}40%,60%{transform:translate3d(80%,0,0)}}@keyframes BeforeAfter-module_SliderLeftRightShake__2mcn5{10%,to{transform:translate3d(-20%,0,0)}20%,80%{transform:translate3d(40%,0,0)}30%,50%,70%{transform:translate3d(-80%,0,0)}40%,60%{transform:translate3d(80%,0,0)}}.SoundDisclaimer-module_soundDisclaimer__31hWh{display:grid;border:1px solid;border-radius:4px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.SoundDisclaimer-module_unmute__1V4Ab,.SoundDisclaimer-module_unmuted__22CJ5{grid-column:1;grid-row:1;display:flex;align-items:center;transition-property:opacity,visibility;transition-duration:.09s;transition-timing-function:ease-out;opacity:0;visibility:hidden;padding:0 15px}.SoundDisclaimer-module_unmute__1V4Ab{position:relative;border:0;background-color:transparent;font:inherit;color:currentColor;text-align:initial;width:100%;z-index:1;cursor:pointer}.SoundDisclaimer-module_active__11_kc{opacity:1;visibility:visible;transition-delay:.09s;transition-duration:.21s;transition-timing-function:ease-in}.SoundDisclaimer-module_soundDisclaimer__31hWh svg{flex:0 0 25px;fill:currentColor;margin-right:15px}.TextBlock-module_text__21Hk4 h2,.TextBlock-module_text__21Hk4 li,.TextBlock-module_text__21Hk4 p{margin:1em 0 0}.TextBlock-module_text__21Hk4 a{color:currentColor;word-wrap:break-word}.TextBlock-module_text__21Hk4 ol,.TextBlock-module_text__21Hk4 ul{margin:0;padding-left:20px;clear:both}.TextBlock-module_text__21Hk4 blockquote{padding:.5em 1em .5em 2em;margin:1em 0 0 .5em;position:relative;overflow:hidden}.TextBlock-module_text__21Hk4 blockquote:before{content:"\201C";font-size:3em;font-weight:700;color:#aaa;position:absolute;top:0;left:0;line-height:1em}.VideoEmbed-module_VideoEmbed__3BUjc{background-color:#000}.VideoEmbed-module_embedPlayer__54NKG{position:absolute;top:0;left:0;bottom:0;right:0}.ExternalLink-module_hidden__3jer0{display:none}.ExternalLink-module_link_item__Blypv{width:45%;vertical-align:top;margin:2% auto;background-color:#fff;color:#000;text-decoration:none;transition:transform .3s}.ExternalLink-module_link_item__Blypv.ExternalLink-module_invert__1zrgN{background-color:#222;color:#fff}.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:29%}.ExternalLink-module_link_item__Blypv:hover{transform:scale(1.05)}.ExternalLink-module_link_item__Blypv:hover .ExternalLink-module_link_title__FZJ-0{text-decoration:underline}.ExternalLink-module_link_thumbnail__2_BHq{width:auto;background-repeat:no-repeat;background-size:cover;padding-top:56.25%;position:relative}.ExternalLink-module_link_details__lRhKU{margin:20px}.ExternalLink-module_link_details__lRhKU>.ExternalLink-module_link_title__FZJ-0{font-size:1.2em;font-weight:700;margin-bottom:20px}.ExternalLink-module_link_details__lRhKU>p{width:100%;white-space:normal;line-height:1.3em}.ExternalLink-module_tooltip__18MpC{position:absolute;left:50%;top:80px;width:180px;padding:5px;margin-left:-95px;background-color:#444;color:#fff;border:1px solid #fff;opacity:.9;font-size:13px;text-align:center;white-space:normal}.ExternalLink-module_tooltip__18MpC>span{display:block;color:#fff;text-decoration:underline}@media only screen and (max-width:600px){.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:45%}}@media only screen and (max-width:350px){.ExternalLink-module_link_item__Blypv,.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:85%}}.ExternalLinkList-module_ext_links_container__16IIo{display:flex;flex-wrap:wrap;border-collapse:separate;border-spacing:10px;min-height:240px;width:auto;height:auto;pointer-events:auto;position:relative;transition:opacity .5s;transition-timing-function:cubic-bezier(.1,.57,.1,1);transition-duration:0ms}.DataWrapperChart-module_container__2eZ15{min-height:200px;padding:20px 5%}.DataWrapperChart-module_container__2eZ15>iframe{width:100%;height:100%;position:relative;top:0;border:0}
1
+ .Heading-module_root__33TFw{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;margin-top:.2em;margin-bottom:0;padding-top:.3em}@media (min-width:951px){.Heading-module_right__1TJKF{text-align:right}}.Heading-module_center__38lDY{text-align:center}@media (orientation:landscape){.Heading-module_first__1PMJX{padding-top:25%}}.BeforeAfter-module_sliderStart__2C5cN{background-color:#fff;position:absolute;z-index:1}.BeforeAfter-module_container__2Lm06{height:100%;--frame1pos:-8;--frame2pos:16;--frame3pos:-32;--frame4pos:32;--frame1px:calc(var(--frame1pos)*1px);--frame2px:calc(var(--frame2pos)*1px);--frame3px:calc(var(--frame3pos)*1px);--frame4px:calc(var(--frame4pos)*1px)}.BeforeAfter-module_container__2Lm06>div{height:100%!important}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe>div>div:nth-child(3){-webkit-animation:BeforeAfter-module_SliderLeftRightShake__2mcn5 1.5s cubic-bezier(.36,.07,.19,.97);animation:BeforeAfter-module_SliderLeftRightShake__2mcn5 1.5s cubic-bezier(.36,.07,.19,.97)}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe div img:nth-child(2){-webkit-animation:BeforeAfter-module_BeforeImageLeftRightShake__38m9V 1.5s cubic-bezier(.36,.07,.19,.97);animation:BeforeAfter-module_BeforeImageLeftRightShake__38m9V 1.5s cubic-bezier(.36,.07,.19,.97)}.BeforeAfter-module_container__2Lm06 div div:nth-child(4) div{transition:opacity .1s ease-out .3s!important}.BeforeAfter-module_container__2Lm06.BeforeAfter-module_wiggle__3nVSe div img:first-child{-webkit-animation:BeforeAfter-module_AfterImageLeftRightShake__3WMf1 1.5s cubic-bezier(.36,.07,.19,.97);animation:BeforeAfter-module_AfterImageLeftRightShake__3WMf1 1.5s cubic-bezier(.36,.07,.19,.97)}.BeforeAfter-module_container__2Lm06 div div:nth-child(5) div{transition:opacity .1s ease-out .3s!important}@-webkit-keyframes BeforeAfter-module_BeforeImageLeftRightShake__38m9V{0%,to{clip:rect(auto,var(--initial-rect-width),auto,auto)}10%,90%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame1px)),auto,auto)}20%,80%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame2px)),auto,auto)}30%,50%,70%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame3px)),auto,auto)}40%,60%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame4px)),auto,auto)}}@keyframes BeforeAfter-module_BeforeImageLeftRightShake__38m9V{0%,to{clip:rect(auto,var(--initial-rect-width),auto,auto)}10%,90%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame1px)),auto,auto)}20%,80%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame2px)),auto,auto)}30%,50%,70%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame3px)),auto,auto)}40%,60%{clip:rect(auto,calc(var(--initial-rect-width) + var(--frame4px)),auto,auto)}}@-webkit-keyframes BeforeAfter-module_AfterImageLeftRightShake__3WMf1{0%,to{clip:rect(auto,auto,auto,var(--initial-rect-width))}10%,90%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame1px)))}20%,80%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame2px)))}30%,50%,70%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame3px)))}40%,60%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame4px)))}}@keyframes BeforeAfter-module_AfterImageLeftRightShake__3WMf1{0%,to{clip:rect(auto,auto,auto,var(--initial-rect-width))}10%,90%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame1px)))}20%,80%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame2px)))}30%,50%,70%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame3px)))}40%,60%{clip:rect(auto,auto,auto,calc(var(--initial-rect-width) + var(--frame4px)))}}@-webkit-keyframes BeforeAfter-module_SliderLeftRightShake__2mcn5{0%,to{margin-left:0}10%,90%{margin-left:var(--frame1px)}20%,80%{margin-left:var(--frame2px)}30%,50%,70%{margin-left:var(--frame3px)}40%,60%{margin-left:var(--frame4px)}}@keyframes BeforeAfter-module_SliderLeftRightShake__2mcn5{0%,to{margin-left:0}10%,90%{margin-left:var(--frame1px)}20%,80%{margin-left:var(--frame2px)}30%,50%,70%{margin-left:var(--frame3px)}40%,60%{margin-left:var(--frame4px)}}.SoundDisclaimer-module_soundDisclaimer__31hWh{display:grid;border:1px solid;border-radius:4px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.SoundDisclaimer-module_unmute__1V4Ab,.SoundDisclaimer-module_unmuted__22CJ5{grid-column:1;grid-row:1;display:flex;align-items:center;transition-property:opacity,visibility;transition-duration:.09s;transition-timing-function:ease-out;opacity:0;visibility:hidden;padding:0 15px}.SoundDisclaimer-module_unmute__1V4Ab{position:relative;border:0;background-color:transparent;font:inherit;color:currentColor;text-align:initial;width:100%;z-index:1;cursor:pointer}.SoundDisclaimer-module_active__11_kc{opacity:1;visibility:visible;transition-delay:.09s;transition-duration:.21s;transition-timing-function:ease-in}.SoundDisclaimer-module_soundDisclaimer__31hWh svg{flex:0 0 25px;fill:currentColor;margin-right:15px}.TextBlock-module_text__21Hk4 h2,.TextBlock-module_text__21Hk4 li,.TextBlock-module_text__21Hk4 p{margin:1em 0 0}.TextBlock-module_text__21Hk4 h2{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word}.TextBlock-module_text__21Hk4 a{color:currentColor;word-wrap:break-word}.TextBlock-module_text__21Hk4 ol,.TextBlock-module_text__21Hk4 ul{margin:0;padding-left:20px;clear:both}.TextBlock-module_text__21Hk4 blockquote{padding:.5em 1em .5em 2em;margin:1em 0 0 .5em;position:relative;overflow:hidden}.TextBlock-module_text__21Hk4 blockquote:before{content:"\201C";font-size:3em;font-weight:700;color:#aaa;position:absolute;top:0;left:0;line-height:1em}.VideoEmbed-module_VideoEmbed__3BUjc{background-color:#000;color:#fff}.VideoEmbed-module_embedPlayer__54NKG{position:absolute;top:0;left:0;bottom:0;right:0}.ExternalLink-module_hidden__3jer0{display:none}.ExternalLink-module_link_item__Blypv{width:45%;vertical-align:top;margin:2% auto;background-color:#fff;color:#000;text-decoration:none;transition:transform .3s}.ExternalLink-module_link_item__Blypv.ExternalLink-module_invert__1zrgN{background-color:#222;color:#fff}.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:29%}.ExternalLink-module_link_item__Blypv:hover{transform:scale(1.05)}.ExternalLink-module_link_item__Blypv:hover .ExternalLink-module_link_title__FZJ-0{text-decoration:underline}.ExternalLink-module_link_thumbnail__2_BHq{width:auto;background-repeat:no-repeat;background-size:cover;padding-top:56.25%;position:relative}.ExternalLink-module_link_details__lRhKU{margin:20px}.ExternalLink-module_link_details__lRhKU>.ExternalLink-module_link_title__FZJ-0{font-size:1.2em;font-weight:700;margin-bottom:20px}.ExternalLink-module_link_details__lRhKU>p{width:100%;white-space:normal;line-height:1.3em}.ExternalLink-module_tooltip__18MpC{position:absolute;left:50%;top:80px;width:180px;padding:5px;margin-left:-95px;background-color:#444;color:#fff;border:1px solid #fff;opacity:.9;font-size:13px;text-align:center;white-space:normal}.ExternalLink-module_tooltip__18MpC>span{display:block;color:#fff;text-decoration:underline}@media only screen and (max-width:600px){.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:45%}}@media only screen and (max-width:350px){.ExternalLink-module_link_item__Blypv,.ExternalLink-module_link_item__Blypv.ExternalLink-module_layout_center__3NRpQ{width:85%}}.ExternalLinkList-module_ext_links_container__16IIo{display:flex;flex-wrap:wrap;border-collapse:separate;border-spacing:10px;min-height:240px;width:auto;height:auto;pointer-events:auto;position:relative;transition:opacity .5s;transition-timing-function:cubic-bezier(.1,.57,.1,1);transition-duration:0ms}.DataWrapperChart-module_container__2eZ15{min-height:200px;padding:20px 5%}.DataWrapperChart-module_container__2eZ15>iframe{width:100%;height:100%;position:relative;top:0;border:0}
@@ -1,7 +1,8 @@
1
- import { useContentElementConfigurationUpdate, useI18n, withShadowClassName, Text, EditableInlineText, frontend, useFile, useContentElementEditorState, ViewportDependentPillarBoxes, useContentElementLifecycle, Figure, Image, usePlayerState, useAudioFocus, MediaInteractionTracking, VideoPlayerControls, VideoPlayer, AudioPlayerControls, AudioPlayer, useMediaMuted, EditableText, ThirdPartyOptOutInfo, ThirdPartyOptIn, useDarkBackground, textColorForBackgroundColor } from 'pageflow-scrolled/frontend';
2
- import React, { useRef, useState, useEffect } from 'react';
1
+ import { useContentElementConfigurationUpdate, useI18n, withShadowClassName, Text, EditableInlineText, frontend, useFile, useContentElementEditorState, ViewportDependentPillarBoxes, useContentElementLifecycle, Figure, Image, usePlayerState, useAudioFocus, MediaInteractionTracking, VideoPlayerControls, VideoPlayer, AudioPlayerControls, AudioPlayer, useMediaMuted, EditableText, ThirdPartyOptOutInfo, ThirdPartyOptIn, useDarkBackground, textColorForBackgroundColor, Panorama } from 'pageflow-scrolled/frontend';
2
+ import React, { useState, useEffect, useRef } from 'react';
3
3
  import classNames from 'classnames';
4
4
  import ReactCompareImage from 'react-compare-image';
5
+ import Measure from 'react-measure';
5
6
  import { media } from 'pageflow/frontend';
6
7
  import ReactPlayer from 'react-player';
7
8
 
@@ -20,7 +21,7 @@ function _defineProperty(obj, key, value) {
20
21
  return obj;
21
22
  }
22
23
 
23
- var styles = {"root":"Heading-module_root__33TFw","first":"Heading-module_first__1PMJX"};
24
+ var styles = {"root":"Heading-module_root__33TFw","right":"Heading-module_right__1TJKF","center":"Heading-module_center__38lDY","first":"Heading-module_first__1PMJX"};
24
25
 
25
26
  function Heading(_ref) {
26
27
  var configuration = _ref.configuration,
@@ -38,7 +39,7 @@ function Heading(_ref) {
38
39
  return (
39
40
  /*#__PURE__*/
40
41
  React.createElement("h1", {
41
- className: classNames(styles.root, _defineProperty({}, styles.first, firstSectionInEntry), _defineProperty({}, withShadowClassName, !sectionProps.invert))
42
+ className: classNames(styles.root, _defineProperty({}, styles.first, firstSectionInEntry), _defineProperty({}, styles[sectionProps.layout], configuration.position === 'wide'), _defineProperty({}, withShadowClassName, !sectionProps.invert))
42
43
  },
43
44
  /*#__PURE__*/
44
45
  React.createElement(Text, {
@@ -164,8 +165,6 @@ var placeholderFile = {
164
165
  height: 403
165
166
  };
166
167
  function BeforeAfter(_ref) {
167
- var _cx;
168
-
169
168
  var isActive = _ref.isActive,
170
169
  load = _ref.load,
171
170
  position = _ref.position,
@@ -177,32 +176,24 @@ function BeforeAfter(_ref) {
177
176
  slider = _ref.slider,
178
177
  slider_color = _ref.slider_color,
179
178
  slider_handle = _ref.slider_handle;
180
- var beforeAfterRef = useRef();
181
- var current = beforeAfterRef.current;
182
179
 
183
180
  var _useState = useState(false),
184
181
  _useState2 = _slicedToArray(_useState, 2),
185
- wiggled = _useState2[0],
186
- setWiggled = _useState2[1];
182
+ wiggle = _useState2[0],
183
+ setWiggle = _useState2[1];
187
184
 
188
185
  var _useState3 = useState(false),
189
186
  _useState4 = _slicedToArray(_useState3, 2),
190
- wiggle = _useState4[0],
191
- setWiggle = _useState4[1];
187
+ moved = _useState4[0],
188
+ setMoved = _useState4[1];
192
189
 
193
190
  useEffect(function () {
194
- var node = current;
195
-
196
- if (node) {
197
- // Only wiggle once per element, when it is active for the first
198
- // time
199
- var shouldWiggle = !wiggled && isActive;
200
- setWiggle(shouldWiggle); // If wiggle was just set, mark this element as one that already
201
- // wiggled
202
-
203
- !wiggled && setWiggled(shouldWiggle);
204
- }
205
- }, [isActive, current]);
191
+ // Only wiggle once per element, when it is active for the first
192
+ // time
193
+ setWiggle(function (wiggle) {
194
+ return wiggle || isActive;
195
+ });
196
+ }, [isActive]);
206
197
  var beforeImage = useFile({
207
198
  collectionName: 'imageFiles',
208
199
  permaId: before_id
@@ -246,19 +237,8 @@ function BeforeAfter(_ref) {
246
237
  sliderLineColor: slider_color
247
238
  });
248
239
  }
249
- } //Since the slider wiggle only the first time, set the variable once for performance purpose.
250
-
240
+ }
251
241
 
252
- useEffect(function () {
253
- if (beforeAfterRef.current) {
254
- // Compute initial slider coordinate and pass it as a CSS
255
- // variable, so that before/after images can wiggle together with
256
- // the slider
257
- var containerWidth = beforeAfterRef.current.getBoundingClientRect().width;
258
- var initialRectWidth = initialSliderPos * containerWidth;
259
- beforeAfterRef.current.style.setProperty('--initial-rect-width', initialRectWidth + 'px');
260
- }
261
- }, [wiggled, initialSliderPos]);
262
242
  return (
263
243
  /*#__PURE__*/
264
244
  React.createElement(ViewportDependentPillarBoxes, {
@@ -266,15 +246,29 @@ function BeforeAfter(_ref) {
266
246
  position: position
267
247
  },
268
248
  /*#__PURE__*/
269
- React.createElement("div", {
270
- ref: beforeAfterRef,
271
- className: classNames((_cx = {}, _defineProperty(_cx, styles$1.selected, isSelected), _defineProperty(_cx, styles$1.wiggle, wiggle), _cx), styles$1.container)
272
- },
273
- /*#__PURE__*/
274
- React.createElement(InitialSliderPositionIndicator, {
275
- parentSelected: isSelected,
276
- position: initial_slider_position
277
- }), renderCompareImage()))
249
+ React.createElement(Measure, {
250
+ bounds: true
251
+ }, function (_ref2) {
252
+ var _cx;
253
+
254
+ var measureRef = _ref2.measureRef,
255
+ contentRect = _ref2.contentRect;
256
+ return (
257
+ /*#__PURE__*/
258
+ React.createElement("div", {
259
+ ref: measureRef,
260
+ style: {
261
+ '--initial-rect-width': contentRect.bounds.width * initialSliderPos + 'px'
262
+ },
263
+ className: classNames((_cx = {}, _defineProperty(_cx, styles$1.selected, isSelected), _defineProperty(_cx, styles$1.wiggle, wiggle && !moved), _cx), styles$1.container)
264
+ },
265
+ /*#__PURE__*/
266
+ React.createElement(InitialSliderPositionIndicator, {
267
+ parentSelected: isSelected,
268
+ position: initial_slider_position
269
+ }), renderCompareImage())
270
+ );
271
+ }))
278
272
  );
279
273
 
280
274
  function renderCompareImage() {
@@ -293,16 +287,16 @@ function BeforeAfter(_ref) {
293
287
  rightImageAlt: afterImageAlt,
294
288
  sliderPositionPercentage: initialSliderPos,
295
289
  onSliderPositionChange: function onSliderPositionChange() {
296
- return setWiggle(false);
290
+ return setMoved(true);
297
291
  }
298
292
  }, opts))
299
293
  );
300
294
  }
301
295
  }
302
296
 
303
- function InitialSliderPositionIndicator(_ref2) {
304
- var parentSelected = _ref2.parentSelected,
305
- position = _ref2.position;
297
+ function InitialSliderPositionIndicator(_ref3) {
298
+ var parentSelected = _ref3.parentSelected,
299
+ position = _ref3.position;
306
300
  var indicatorWidth = '2px';
307
301
  var indicatorStyles = {
308
302
  left: "calc(".concat(position, "% - ").concat(indicatorWidth, "/2)"),
@@ -826,11 +820,12 @@ function PreparedPlayer(_ref2) {
826
820
  onLost: function onLost() {
827
821
  setPlayerState('paused');
828
822
  }
829
- }); // base64-encoded configuration
830
- // => make component re-render on configuration changes
823
+ }); // React player does not re-create player when controls or config
824
+ // prop changes. Ensure key changes to force React to re-mount
825
+ // component.
831
826
 
832
827
  function keyFromConfiguration(config) {
833
- return btoa(JSON.stringify(config));
828
+ return [config.hideControls, config.hideInfo].join('');
834
829
  }
835
830
 
836
831
  return (
@@ -1110,3 +1105,65 @@ frontend.contentElementTypes.register('dataWrapperChart', {
1110
1105
  component: DataWrapperChart,
1111
1106
  lifecycle: true
1112
1107
  });
1108
+
1109
+ function VrImage(_ref) {
1110
+ var configuration = _ref.configuration;
1111
+
1112
+ var _useContentElementLif = useContentElementLifecycle({
1113
+ onActivate: function onActivate() {
1114
+ if (viewerRef.current) {
1115
+ viewerRef.current.lookAt({
1116
+ yaw: viewerRef.current.getYaw() + 20
1117
+ }, 1000);
1118
+ }
1119
+ }
1120
+ }),
1121
+ shouldLoad = _useContentElementLif.shouldLoad;
1122
+
1123
+ var _useContentElementEdi = useContentElementEditorState(),
1124
+ isEditable = _useContentElementEdi.isEditable,
1125
+ isSelected = _useContentElementEdi.isSelected;
1126
+
1127
+ var viewerRef = useRef();
1128
+ var imageFile = useFile({
1129
+ collectionName: 'imageFiles',
1130
+ permaId: configuration.image
1131
+ });
1132
+ return (
1133
+ /*#__PURE__*/
1134
+ React.createElement("div", {
1135
+ style: {
1136
+ pointerEvents: isEditable && !isSelected ? 'none' : undefined
1137
+ }
1138
+ },
1139
+ /*#__PURE__*/
1140
+ React.createElement(Figure, {
1141
+ caption: configuration.caption
1142
+ },
1143
+ /*#__PURE__*/
1144
+ React.createElement(ViewportDependentPillarBoxes, {
1145
+ aspectRatio: configuration.position === 'full' ? 0.5 : 0.75,
1146
+ position: configuration.position,
1147
+ opaque: !!configuration.caption
1148
+ }, renderLazyPanorama(configuration, imageFile, shouldLoad, viewerRef))))
1149
+ );
1150
+ }
1151
+
1152
+ function renderLazyPanorama(configuration, imageFile, shouldLoad, viewerRef) {
1153
+ if (shouldLoad && imageFile && imageFile.isReady) {
1154
+ return (
1155
+ /*#__PURE__*/
1156
+ React.createElement(Panorama, {
1157
+ imageFile: imageFile,
1158
+ initialYaw: configuration.initialYaw,
1159
+ initialPitch: configuration.initialPitch,
1160
+ viewerRef: viewerRef
1161
+ })
1162
+ );
1163
+ }
1164
+ }
1165
+
1166
+ frontend.contentElementTypes.register('vrImage', {
1167
+ component: VrImage,
1168
+ lifecycle: true
1169
+ });