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
@@ -0,0 +1,387 @@
1
+ import 'pageflow/frontend';
2
+ import React, { useMemo, useEffect, useRef, useState } from 'react';
3
+ import ReactDOM from 'react-dom';
4
+ import { b as _objectWithoutProperties, u as useI18n, _ as _slicedToArray, a as _defineProperty } from './i18n-4dc6c377.js';
5
+ import classNames from 'classnames';
6
+ import 'use-context-selector';
7
+ import 'reselect';
8
+ import 'i18n-js';
9
+ import 'slugify';
10
+ import { u as useBrowserFeature } from './useBrowserFeature-91a4c29d.js';
11
+ import { PanoViewer } from '@egjs/view360';
12
+ import screenfull from 'screenfull';
13
+
14
+ function _extends() {
15
+ _extends = Object.assign || function (target) {
16
+ for (var i = 1; i < arguments.length; i++) {
17
+ var source = arguments[i];
18
+
19
+ for (var key in source) {
20
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
21
+ target[key] = source[key];
22
+ }
23
+ }
24
+ }
25
+
26
+ return target;
27
+ };
28
+
29
+ return _extends.apply(this, arguments);
30
+ }
31
+ var EnterFullscreenIcon = (function (_ref) {
32
+ var _ref$styles = _ref.styles,
33
+ styles = _ref$styles === void 0 ? {} : _ref$styles,
34
+ props = _objectWithoutProperties(_ref, ["styles"]);
35
+
36
+ return React.createElement("svg", _extends({
37
+ "aria-hidden": "true",
38
+ "data-prefix": "fas",
39
+ "data-icon": "expand",
40
+ className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-expand"] || "fa-expand") + " " + (styles["fa-w-14"] || "fa-w-14"),
41
+ xmlns: "http://www.w3.org/2000/svg",
42
+ viewBox: "0 0 448 512"
43
+ }, props), React.createElement("path", {
44
+ fill: "currentColor",
45
+ d: "M0 180V56c0-13.3 10.7-24 24-24h124c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H64v84c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12zM288 44v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12V56c0-13.3-10.7-24-24-24H300c-6.6 0-12 5.4-12 12zm148 276h-40c-6.6 0-12 5.4-12 12v84h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24V332c0-6.6-5.4-12-12-12zM160 468v-40c0-6.6-5.4-12-12-12H64v-84c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v124c0 13.3 10.7 24 24 24h124c6.6 0 12-5.4 12-12z"
46
+ }));
47
+ });
48
+
49
+ function _extends$1() {
50
+ _extends$1 = Object.assign || function (target) {
51
+ for (var i = 1; i < arguments.length; i++) {
52
+ var source = arguments[i];
53
+
54
+ for (var key in source) {
55
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
56
+ target[key] = source[key];
57
+ }
58
+ }
59
+ }
60
+
61
+ return target;
62
+ };
63
+
64
+ return _extends$1.apply(this, arguments);
65
+ }
66
+ var ExitFullscreenIcon = (function (_ref) {
67
+ var _ref$styles = _ref.styles,
68
+ styles = _ref$styles === void 0 ? {} : _ref$styles,
69
+ props = _objectWithoutProperties(_ref, ["styles"]);
70
+
71
+ return React.createElement("svg", _extends$1({
72
+ "aria-hidden": "true",
73
+ "data-prefix": "fas",
74
+ "data-icon": "compress",
75
+ className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-compress"] || "fa-compress") + " " + (styles["fa-w-14"] || "fa-w-14"),
76
+ xmlns: "http://www.w3.org/2000/svg",
77
+ viewBox: "0 0 448 512"
78
+ }, props), React.createElement("path", {
79
+ fill: "currentColor",
80
+ d: "M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"
81
+ }));
82
+ });
83
+
84
+ var styles = {"button":"ToggleFullscreenButton-module_button__3iBr8 utils-module_unstyledButton__3rgne"};
85
+
86
+ function ToggleFullscreenButton(props) {
87
+ var _useI18n = useI18n(),
88
+ t = _useI18n.t;
89
+
90
+ return (
91
+ /*#__PURE__*/
92
+ React.createElement("button", {
93
+ className: styles.button,
94
+ title: t(props.isFullscreen ? 'exit_fullscreen' : 'enter_fullscreen', {
95
+ scope: 'pageflow_scrolled.public'
96
+ }),
97
+ onClick: function onClick() {
98
+ return props.isFullscreen ? props.onExit() : props.onEnter();
99
+ }
100
+ }, icon(props))
101
+ );
102
+ }
103
+
104
+ function icon(props) {
105
+ if (props.isFullscreen) {
106
+ return (
107
+ /*#__PURE__*/
108
+ React.createElement(ExitFullscreenIcon, null)
109
+ );
110
+ } else {
111
+ return (
112
+ /*#__PURE__*/
113
+ React.createElement(EnterFullscreenIcon, null)
114
+ );
115
+ }
116
+ }
117
+
118
+ var styles$1 = {"wrapper":"Fullscreen-module_wrapper__300hJ"};
119
+
120
+ function Fullscreen(_ref) {
121
+ var isFullscreen = _ref.isFullscreen,
122
+ children = _ref.children;
123
+ var root = useMemo(function () {
124
+ return document.getElementById('fullscreenRoot');
125
+ }, []);
126
+ useEffect(function () {
127
+ if (isFullscreen) {
128
+ document.body.style.overflow = 'hidden';
129
+ } else {
130
+ document.body.style.overflow = 'initial';
131
+ }
132
+ }, [isFullscreen]);
133
+
134
+ if (isFullscreen) {
135
+ return ReactDOM.createPortal(
136
+ /*#__PURE__*/
137
+ React.createElement("div", {
138
+ className: styles$1.wrapper
139
+ }, children), root);
140
+ } else {
141
+ return children;
142
+ }
143
+ }
144
+
145
+ var styles$2 = {"full":"Viewer-module_full__1q18y","container":"Viewer-module_container__3eJ34 Viewer-module_full__1q18y","controls":"Viewer-module_controls__3BTof","spinner":"Viewer-module_spinner__2oRve","spin":"Viewer-module_spin__3jBR2","isLoading":"Viewer-module_isLoading__sQuGw"};
146
+
147
+ function _extends$2() {
148
+ _extends$2 = Object.assign || function (target) {
149
+ for (var i = 1; i < arguments.length; i++) {
150
+ var source = arguments[i];
151
+
152
+ for (var key in source) {
153
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
154
+ target[key] = source[key];
155
+ }
156
+ }
157
+ }
158
+
159
+ return target;
160
+ };
161
+
162
+ return _extends$2.apply(this, arguments);
163
+ }
164
+ var SpinnerIcon = (function (_ref) {
165
+ var _ref$styles = _ref.styles,
166
+ props = _objectWithoutProperties(_ref, ["styles"]);
167
+
168
+ return React.createElement("svg", _extends$2({
169
+ xmlns: "http://www.w3.org/2000/svg",
170
+ fill: "none",
171
+ viewBox: "0 0 24 24"
172
+ }, props), React.createElement("circle", {
173
+ cx: "12",
174
+ cy: "12",
175
+ r: "10",
176
+ stroke: "currentColor",
177
+ strokeWidth: "4",
178
+ opacity: ".23"
179
+ }), React.createElement("path", {
180
+ fill: "currentColor",
181
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z",
182
+ opacity: ".75"
183
+ }));
184
+ });
185
+
186
+ function Viewer(_ref) {
187
+ var imageFile = _ref.imageFile,
188
+ viewerRef = _ref.viewerRef,
189
+ initialYaw = _ref.initialYaw,
190
+ initialPitch = _ref.initialPitch;
191
+ var elRef = useRef();
192
+ var initialYawRef = useRef(initialYaw);
193
+ var initialPitchRef = useRef(initialPitch);
194
+ var touchSupport = useBrowserFeature('touch support');
195
+
196
+ var _useState = useState(true),
197
+ _useState2 = _slicedToArray(_useState, 2),
198
+ isLoading = _useState2[0],
199
+ setIsLoading = _useState2[1];
200
+
201
+ var _useState3 = useState(false),
202
+ _useState4 = _slicedToArray(_useState3, 2),
203
+ isFullscreen = _useState4[0],
204
+ setIsFullscreen = _useState4[1]; // When toggling to fullscreen mode, this component renders to a
205
+ // portal div in the body of the document. We do not want to recreate
206
+ // the PanoViewer instead to keep its current state (pitch, yaw etc.).
207
+ // We therefore initialize the PanoViewer on a detached DOM element
208
+ // and render a component called DOMNodeContainer which appends the
209
+ // element on each render. React.memo causes the DOMNodeContainer to
210
+ // render only when either
211
+ // - the parent Viewer component is mounted
212
+ // - Fullscreen component switches between using the portal or not
213
+
214
+
215
+ function appendViewerTo(parentNode) {
216
+ if (!elRef.current) {
217
+ elRef.current = document.createElement('div');
218
+ elRef.current.className = styles$2.full;
219
+ viewerRef.current = new PanoViewer(elRef.current, {
220
+ image: imageFile.urls.ultra,
221
+ projectionType: imageFile.configuration.projection === 'equirectangular_stereo' ? PanoViewer.PROJECTION_TYPE.STEREOSCOPIC_EQUI : PanoViewer.PROJECTION_TYPE.EQUIRECTANGULAR,
222
+ touchDirection: touchSupport ? PanoViewer.TOUCH_DIRECTION.YAW : PanoViewer.TOUCH_DIRECTION.ALL,
223
+ useZoom: false,
224
+ yaw: initialYawRef.current,
225
+ pitch: initialPitchRef.current
226
+ });
227
+ viewerRef.current.on(PanoViewer.EVENTS.READY, function () {
228
+ viewerRef.current.updateViewportDimensions();
229
+ setIsLoading(false);
230
+ });
231
+ }
232
+
233
+ parentNode.appendChild(elRef.current);
234
+ viewerRef.current.updateViewportDimensions();
235
+ }
236
+
237
+ useEffect(function () {
238
+ return function () {
239
+ if (elRef.current) {
240
+ viewerRef.current.destroy();
241
+ viewerRef.current = null;
242
+ elRef.current = null;
243
+ }
244
+ };
245
+ }, [viewerRef]);
246
+ useEffect(function () {
247
+ if (initialYawRef.current !== initialYaw) {
248
+ initialYawRef.current = initialYaw;
249
+ viewerRef.current.lookAt({
250
+ yaw: initialYaw
251
+ }, 200);
252
+ }
253
+ }, [initialYaw, viewerRef]);
254
+ useEffect(function () {
255
+ if (initialPitchRef.current !== initialPitch) {
256
+ initialPitchRef.current = initialPitch;
257
+ viewerRef.current.lookAt({
258
+ pitch: initialPitch
259
+ }, 200);
260
+ }
261
+ }, [initialPitch, viewerRef]);
262
+ useEffect(function () {
263
+ function onChange() {
264
+ if (!screenfull.isFullscreen) {
265
+ setIsFullscreen(false);
266
+ }
267
+ }
268
+
269
+ if (screenfull.isEnabled) {
270
+ screenfull.on('change', onChange);
271
+ return function () {
272
+ return screenfull.off('change', onChange);
273
+ };
274
+ }
275
+ }, []);
276
+ useEffect(function () {
277
+ function onChange() {
278
+ viewerRef.current.updateViewportDimensions();
279
+ }
280
+
281
+ window.addEventListener('resize', onChange);
282
+ return function () {
283
+ return window.removeEventListener('resize', onChange);
284
+ };
285
+ }, [viewerRef]);
286
+ useEffect(function () {
287
+ if (isFullscreen) {
288
+ viewerRef.current.setTouchDirection(PanoViewer.TOUCH_DIRECTION.ALL);
289
+ viewerRef.current.setGyroMode(PanoViewer.GYRO_MODE.YAWPITCH);
290
+ viewerRef.current.setUseZoom(true);
291
+ } else {
292
+ if (touchSupport) {
293
+ viewerRef.current.setTouchDirection(PanoViewer.TOUCH_DIRECTION.YAW);
294
+ viewerRef.current.lookAt({
295
+ pitch: 0,
296
+ fov: 65
297
+ });
298
+ } else {
299
+ viewerRef.current.lookAt({
300
+ fov: 65
301
+ });
302
+ }
303
+
304
+ viewerRef.current.setGyroMode(PanoViewer.GYRO_MODE.NONE);
305
+ viewerRef.current.setUseZoom(false);
306
+ }
307
+ }, [isFullscreen, viewerRef, touchSupport]);
308
+
309
+ function preventDefaultForArrowUpDown(event) {
310
+ if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
311
+ event.preventDefault();
312
+ }
313
+ }
314
+
315
+ function enterFullscreen() {
316
+ if (screenfull.isEnabled) {
317
+ screenfull.request();
318
+ }
319
+
320
+ setIsFullscreen(true);
321
+ viewerRef.current.enableSensor();
322
+ }
323
+
324
+ function exitFullscreen() {
325
+ if (screenfull.isEnabled) {
326
+ screenfull.exit();
327
+ }
328
+
329
+ setIsFullscreen(false);
330
+ }
331
+
332
+ return (
333
+ /*#__PURE__*/
334
+ React.createElement(Fullscreen, {
335
+ isFullscreen: isFullscreen
336
+ },
337
+ /*#__PURE__*/
338
+ React.createElement("div", {
339
+ className: styles$2.container,
340
+ onKeyDown: preventDefaultForArrowUpDown
341
+ },
342
+ /*#__PURE__*/
343
+ React.createElement(DOMNodeContainer, {
344
+ className: styles$2.full,
345
+ onUpdate: function onUpdate(el) {
346
+ return appendViewerTo(el);
347
+ }
348
+ })),
349
+ /*#__PURE__*/
350
+ React.createElement(SpinnerIcon, {
351
+ className: classNames(styles$2.spinner, _defineProperty({}, styles$2.isLoading, isLoading))
352
+ }),
353
+ /*#__PURE__*/
354
+ React.createElement("div", {
355
+ className: styles$2.controls
356
+ },
357
+ /*#__PURE__*/
358
+ React.createElement(ToggleFullscreenButton, {
359
+ isFullscreen: isFullscreen,
360
+ onEnter: enterFullscreen,
361
+ onExit: exitFullscreen
362
+ })))
363
+ );
364
+ }
365
+ var DOMNodeContainer = React.memo(function (_ref2) {
366
+ var className = _ref2.className,
367
+ onUpdate = _ref2.onUpdate;
368
+ var ref = useRef();
369
+ useEffect(function () {
370
+ var current = ref.current;
371
+ onUpdate(current);
372
+ return function () {
373
+ current.removeChild(current.firstChild);
374
+ };
375
+ });
376
+ return (
377
+ /*#__PURE__*/
378
+ React.createElement("div", {
379
+ ref: ref,
380
+ className: className
381
+ })
382
+ );
383
+ }, function () {
384
+ return true;
385
+ });
386
+
387
+ export default Viewer;
@@ -1,6 +1,6 @@
1
1
  import React, { Component } from 'react';
2
- import { b as _inherits, a as _classCallCheck, e as _assertThisInitialized, _ as _createClass, c as _getPrototypeOf, d as _possibleConstructorReturn } from './getPrototypeOf-63c7c8e8.js';
3
2
  import Measure from 'react-measure';
3
+ import { b as _inherits, a as _classCallCheck, e as _assertThisInitialized, _ as _createClass, c as _getPrototypeOf, d as _possibleConstructorReturn } from './getPrototypeOf-63c7c8e8.js';
4
4
  import assign from 'deep-assign';
5
5
  import WaveSurfer from 'wavesurfer.js';
6
6
 
@@ -1,10 +1,11 @@
1
1
  import React, { useMemo, useState, useCallback, useContext, useRef, useEffect, createContext, useLayoutEffect, memo } from 'react';
2
- import { _ as _slicedToArray, R as ContentElementEditorCommandEmitterContext, t as usePostMessageListener, A as useEntryStateDispatch, a as _defineProperty, b as _objectWithoutProperties, u as useI18n, U as MotifAreaVisibilityProvider, V as ForcePaddingContext, W as updateContentElementConfiguration, X as ContentElementConfigurationUpdateContext, Y as ContentElementEditorStateContext, G as api, J as useContentElementEditorState, Z as LayoutWithoutInlineEditing, $ as renderElement, a0 as renderLeaf, m as _objectSpread2, y as _toConsumableArray, I as useContentElementEditorCommandSubscription, T as Text$1, P as PhonePlatformContext } from './EditableText-43c50894.js';
2
+ import { _ as _slicedToArray, r as useEntryStateDispatch, a as _defineProperty, b as _objectWithoutProperties, u as useI18n, w as updateContentElementConfiguration, k as _objectSpread2, p as _toConsumableArray } from './i18n-4dc6c377.js';
3
3
  import classNames from 'classnames';
4
4
  import 'use-context-selector';
5
5
  import 'reselect';
6
6
  import 'i18n-js';
7
7
  import 'slugify';
8
+ import { C as ContentElementEditorCommandEmitterContext, d as usePostMessageListener, m as MotifAreaVisibilityProvider, n as ForcePaddingContext, o as ContentElementConfigurationUpdateContext, p as ContentElementEditorStateContext, f as api, i as useContentElementEditorState, q as LayoutWithoutInlineEditing, r as renderElement, s as renderLeaf, h as useContentElementEditorCommandSubscription, T as Text$1, P as PhonePlatformContext } from './EditableText-7093fd0e.js';
8
9
  import './getPrototypeOf-63c7c8e8.js';
9
10
  import BackboneEvents from 'backbone-events-standalone';
10
11
  import { DndProvider, useDrop, useDrag } from 'react-dnd';
@@ -0,0 +1,1092 @@
1
+ import React, { useReducer, useMemo, useCallback, createContext as createContext$1, useContext } from 'react';
2
+ import { createContext, useContextSelector } from 'use-context-selector';
3
+ import { createSelectorCreator, defaultMemoize, createSelector } from 'reselect';
4
+ import I18n from 'i18n-js';
5
+ import slugify from 'slugify';
6
+
7
+ function _defineProperty(obj, key, value) {
8
+ if (key in obj) {
9
+ Object.defineProperty(obj, key, {
10
+ value: value,
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true
14
+ });
15
+ } else {
16
+ obj[key] = value;
17
+ }
18
+
19
+ return obj;
20
+ }
21
+
22
+ function _arrayWithHoles(arr) {
23
+ if (Array.isArray(arr)) return arr;
24
+ }
25
+
26
+ function _iterableToArrayLimit(arr, i) {
27
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
28
+ var _arr = [];
29
+ var _n = true;
30
+ var _d = false;
31
+ var _e = undefined;
32
+
33
+ try {
34
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
35
+ _arr.push(_s.value);
36
+
37
+ if (i && _arr.length === i) break;
38
+ }
39
+ } catch (err) {
40
+ _d = true;
41
+ _e = err;
42
+ } finally {
43
+ try {
44
+ if (!_n && _i["return"] != null) _i["return"]();
45
+ } finally {
46
+ if (_d) throw _e;
47
+ }
48
+ }
49
+
50
+ return _arr;
51
+ }
52
+
53
+ function _arrayLikeToArray(arr, len) {
54
+ if (len == null || len > arr.length) len = arr.length;
55
+
56
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
57
+ arr2[i] = arr[i];
58
+ }
59
+
60
+ return arr2;
61
+ }
62
+
63
+ function _unsupportedIterableToArray(o, minLen) {
64
+ if (!o) return;
65
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
66
+ var n = Object.prototype.toString.call(o).slice(8, -1);
67
+ if (n === "Object" && o.constructor) n = o.constructor.name;
68
+ if (n === "Map" || n === "Set") return Array.from(n);
69
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
70
+ }
71
+
72
+ function _nonIterableRest() {
73
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
74
+ }
75
+
76
+ function _slicedToArray(arr, i) {
77
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
78
+ }
79
+
80
+ function ownKeys(object, enumerableOnly) {
81
+ var keys = Object.keys(object);
82
+
83
+ if (Object.getOwnPropertySymbols) {
84
+ var symbols = Object.getOwnPropertySymbols(object);
85
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
86
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
87
+ });
88
+ keys.push.apply(keys, symbols);
89
+ }
90
+
91
+ return keys;
92
+ }
93
+
94
+ function _objectSpread2(target) {
95
+ for (var i = 1; i < arguments.length; i++) {
96
+ var source = arguments[i] != null ? arguments[i] : {};
97
+
98
+ if (i % 2) {
99
+ ownKeys(Object(source), true).forEach(function (key) {
100
+ _defineProperty(target, key, source[key]);
101
+ });
102
+ } else if (Object.getOwnPropertyDescriptors) {
103
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
104
+ } else {
105
+ ownKeys(Object(source)).forEach(function (key) {
106
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
107
+ });
108
+ }
109
+ }
110
+
111
+ return target;
112
+ }
113
+
114
+ var PREFIX = 'PAGEFLOW_SCROLLED_COLLECTION';
115
+ var RESET = "".concat(PREFIX, "_RESET");
116
+ var ADD = "".concat(PREFIX, "_ADD");
117
+ var CHANGE = "".concat(PREFIX, "_CHANGE");
118
+ var PATCH_CONFIGURATION = "".concat(PREFIX, "_PATCH_CONFIGURATION");
119
+ var REMOVE = "".concat(PREFIX, "_REMOVE");
120
+ var SORT = "".concat(PREFIX, "_SORT");
121
+ function useCollections() {
122
+ var seed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
123
+
124
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
125
+ keyAttribute = _ref.keyAttribute;
126
+
127
+ return useReducer(reducer, Object.keys(seed).reduce(function (result, key) {
128
+ result[key] = init(seed[key], keyAttribute);
129
+ return result;
130
+ }, {}));
131
+ }
132
+
133
+ function reducer(state, action) {
134
+ var collectionName = action.payload.collectionName;
135
+ var keyAttribute = action.payload.keyAttribute;
136
+
137
+ switch (action.type) {
138
+ case RESET:
139
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, init(action.payload.items, keyAttribute)));
140
+
141
+ case ADD:
142
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, {
143
+ order: action.payload.order,
144
+ items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, action.payload.attributes[keyAttribute], action.payload.attributes))
145
+ }));
146
+
147
+ case CHANGE:
148
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, {
149
+ order: state[collectionName].order,
150
+ items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, action.payload.attributes[keyAttribute], action.payload.attributes))
151
+ }));
152
+
153
+ case PATCH_CONFIGURATION:
154
+ var key = action.payload.key;
155
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, {
156
+ order: state[collectionName].order,
157
+ items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, key, _objectSpread2(_objectSpread2({}, state[collectionName].items[key]), {}, {
158
+ configuration: _objectSpread2(_objectSpread2({}, state[collectionName].items[key].configuration), action.payload.configuration)
159
+ })))
160
+ }));
161
+
162
+ case REMOVE:
163
+ var clonedItems = _objectSpread2({}, state[collectionName].items);
164
+
165
+ delete clonedItems[action.payload.key];
166
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, {
167
+ order: action.payload.order,
168
+ items: clonedItems
169
+ }));
170
+
171
+ case SORT:
172
+ return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, {
173
+ order: action.payload.order,
174
+ items: state[collectionName].items
175
+ }));
176
+
177
+ default:
178
+ return state;
179
+ }
180
+ }
181
+
182
+ function init(items) {
183
+ var keyAttribute = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'id';
184
+ items = items.filter(function (item) {
185
+ return item[keyAttribute];
186
+ });
187
+ return {
188
+ order: items.map(function (item) {
189
+ return item[keyAttribute];
190
+ }),
191
+ items: items.reduce(function (result, item) {
192
+ result[item[keyAttribute]] = item;
193
+ return result;
194
+ }, {})
195
+ };
196
+ }
197
+
198
+ function updateConfiguration(_ref2) {
199
+ var dispatch = _ref2.dispatch,
200
+ name = _ref2.name,
201
+ key = _ref2.key,
202
+ configuration = _ref2.configuration;
203
+ dispatch({
204
+ type: PATCH_CONFIGURATION,
205
+ payload: {
206
+ collectionName: name,
207
+ key: key,
208
+ configuration: configuration
209
+ }
210
+ });
211
+ }
212
+ function getItem(state, collectionName, key) {
213
+ if (state[collectionName]) {
214
+ return state[collectionName].items[key];
215
+ }
216
+ }
217
+ function createItemsSelector(collectionName, filter) {
218
+ if (filter) {
219
+ var itemsSelector = createItemsSelector(collectionName);
220
+ return createShallowEqualArraysSelector(function (collections) {
221
+ return itemsSelector(collections).filter(filter);
222
+ }, function (items) {
223
+ return items;
224
+ });
225
+ }
226
+
227
+ return createSelector(function (collections) {
228
+ return collections[collectionName];
229
+ }, function (collection) {
230
+ if (collection) {
231
+ var items = collection.items;
232
+ return collection.order.map(function (key) {
233
+ return items[key];
234
+ });
235
+ } else {
236
+ return [];
237
+ }
238
+ });
239
+ }
240
+ var createShallowEqualArraysSelector = createSelectorCreator(defaultMemoize, shallowEqualArrays);
241
+
242
+ function shallowEqualArrays(a, b) {
243
+ return a.length === b.length && a.every(function (item, index) {
244
+ return item === b[index];
245
+ });
246
+ }
247
+
248
+ var Context = createContext();
249
+ function EntryStateProvider(_ref) {
250
+ var seed = _ref.seed,
251
+ children = _ref.children;
252
+
253
+ var _useCollections = useCollections(seed.collections, {
254
+ keyAttribute: 'permaId'
255
+ }),
256
+ _useCollections2 = _slicedToArray(_useCollections, 2),
257
+ collections = _useCollections2[0],
258
+ dispatch = _useCollections2[1];
259
+
260
+ var value = useMemo(function () {
261
+ return {
262
+ entryState: {
263
+ collections: collections,
264
+ config: seed.config
265
+ },
266
+ dispatch: dispatch
267
+ };
268
+ }, [collections, dispatch, seed]);
269
+ return (
270
+ /*#__PURE__*/
271
+ React.createElement(Context.Provider, {
272
+ value: value
273
+ }, children)
274
+ );
275
+ }
276
+
277
+ function useEntryState() {
278
+ var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (entryState) {
279
+ return entryState;
280
+ };
281
+ return useContextSelector(Context, function (value) {
282
+ return selector(value.entryState);
283
+ });
284
+ }
285
+
286
+ function useEntryStateDispatch() {
287
+ return useContextSelector(Context, function (value) {
288
+ return value.dispatch;
289
+ });
290
+ }
291
+ function useEntryStateConfig() {
292
+ return useEntryState(function (entryState) {
293
+ return entryState.config;
294
+ });
295
+ }
296
+ function useEntryStateCollectionItem(collectionName, key) {
297
+ return useEntryState(function (entryState) {
298
+ return getItem(entryState.collections, collectionName, key);
299
+ });
300
+ }
301
+ function useEntryStateCollectionItems(collectionName, filter) {
302
+ var itemsSelector = useMemo(function () {
303
+ return createItemsSelector(collectionName, filter);
304
+ }, [collectionName, filter]);
305
+ return useEntryState(function (entryState) {
306
+ return itemsSelector(entryState.collections);
307
+ });
308
+ }
309
+
310
+ /**
311
+ * Returns a nested data structure representing the metadata of the entry.
312
+ *
313
+ * @example
314
+ *
315
+ * const metaData = useEntryMetadata();
316
+ * metaData // =>
317
+ * {
318
+ * id: 5,
319
+ * locale: 'en',
320
+ * shareProviders: {email: false, facebook: true},
321
+ * share_url: 'http://test.host/test',
322
+ * credits: 'Credits: Pageflow'
323
+ * }
324
+ */
325
+
326
+ function useEntryMetadata() {
327
+ var entries = useEntryStateCollectionItems('entries');
328
+ return useMemo(function () {
329
+ return entries[0];
330
+ }, [entries]);
331
+ }
332
+
333
+ function _objectWithoutPropertiesLoose(source, excluded) {
334
+ if (source == null) return {};
335
+ var target = {};
336
+ var sourceKeys = Object.keys(source);
337
+ var key, i;
338
+
339
+ for (i = 0; i < sourceKeys.length; i++) {
340
+ key = sourceKeys[i];
341
+ if (excluded.indexOf(key) >= 0) continue;
342
+ target[key] = source[key];
343
+ }
344
+
345
+ return target;
346
+ }
347
+
348
+ function _objectWithoutProperties(source, excluded) {
349
+ if (source == null) return {};
350
+ var target = _objectWithoutPropertiesLoose(source, excluded);
351
+ var key, i;
352
+
353
+ if (Object.getOwnPropertySymbols) {
354
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
355
+
356
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
357
+ key = sourceSymbolKeys[i];
358
+ if (excluded.indexOf(key) >= 0) continue;
359
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
360
+ target[key] = source[key];
361
+ }
362
+ }
363
+
364
+ return target;
365
+ }
366
+
367
+ function _extends() {
368
+ _extends = Object.assign || function (target) {
369
+ for (var i = 1; i < arguments.length; i++) {
370
+ var source = arguments[i];
371
+
372
+ for (var key in source) {
373
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
374
+ target[key] = source[key];
375
+ }
376
+ }
377
+ }
378
+
379
+ return target;
380
+ };
381
+
382
+ return _extends.apply(this, arguments);
383
+ }
384
+ var EmailIcon = (function (_ref) {
385
+ var _ref$styles = _ref.styles,
386
+ props = _objectWithoutProperties(_ref, ["styles"]);
387
+
388
+ return React.createElement("svg", _extends({
389
+ xmlns: "http://www.w3.org/2000/svg",
390
+ viewBox: "0 0 612 612"
391
+ }, props), React.createElement("path", {
392
+ d: "M573.75 57.375H38.25C17.136 57.375 0 74.511 0 95.625v420.75c0 21.133 17.136 38.25 38.25 38.25h535.5c21.133 0 38.25-17.117 38.25-38.25V95.625c0-21.114-17.117-38.25-38.25-38.25zM554.625 497.25H57.375V204.657l224.03 187.999c7.134 5.967 15.874 8.97 24.595 8.97 8.74 0 17.461-3.003 24.595-8.97l224.03-187.999V497.25zm0-367.487L306 338.379 57.375 129.763V114.75h497.25v15.013z"
393
+ }));
394
+ });
395
+
396
+ function _extends$1() {
397
+ _extends$1 = Object.assign || function (target) {
398
+ for (var i = 1; i < arguments.length; i++) {
399
+ var source = arguments[i];
400
+
401
+ for (var key in source) {
402
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
403
+ target[key] = source[key];
404
+ }
405
+ }
406
+ }
407
+
408
+ return target;
409
+ };
410
+
411
+ return _extends$1.apply(this, arguments);
412
+ }
413
+ var FacebookIcon = (function (_ref) {
414
+ var _ref$styles = _ref.styles,
415
+ props = _objectWithoutProperties(_ref, ["styles"]);
416
+
417
+ return React.createElement("svg", _extends$1({
418
+ xmlns: "http://www.w3.org/2000/svg",
419
+ viewBox: "0 0 430.113 430.114"
420
+ }, props), React.createElement("path", {
421
+ d: "M158.081 83.3v59.218h-43.385v72.412h43.385v215.183h89.122V214.936h59.805s5.601-34.721 8.316-72.685H247.54V92.74c0-7.4 9.717-17.354 19.321-17.354h48.557V.001h-66.021C155.878-.004 158.081 72.48 158.081 83.3z"
422
+ }));
423
+ });
424
+
425
+ function _extends$2() {
426
+ _extends$2 = Object.assign || function (target) {
427
+ for (var i = 1; i < arguments.length; i++) {
428
+ var source = arguments[i];
429
+
430
+ for (var key in source) {
431
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
432
+ target[key] = source[key];
433
+ }
434
+ }
435
+ }
436
+
437
+ return target;
438
+ };
439
+
440
+ return _extends$2.apply(this, arguments);
441
+ }
442
+ var LinkedInIcon = (function (_ref) {
443
+ var _ref$styles = _ref.styles,
444
+ props = _objectWithoutProperties(_ref, ["styles"]);
445
+
446
+ return React.createElement("svg", _extends$2({
447
+ xmlns: "http://www.w3.org/2000/svg",
448
+ viewBox: "0 0 430.117 430.117"
449
+ }, props), React.createElement("path", {
450
+ d: "M430.117 261.543V420.56h-92.188V272.193c0-37.271-13.334-62.707-46.703-62.707-25.473 0-40.632 17.142-47.301 33.724-2.432 5.928-3.058 14.179-3.058 22.477V420.56h-92.219s1.242-251.285 0-277.32h92.21v39.309c-.187.294-.43.611-.606.896h.606v-.896c12.251-18.869 34.13-45.824 83.102-45.824 60.673-.001 106.157 39.636 106.157 124.818zM52.183 9.558C20.635 9.558 0 30.251 0 57.463c0 26.619 20.038 47.94 50.959 47.94h.616c32.159 0 52.159-21.317 52.159-47.94-.606-27.212-20-47.905-51.551-47.905zM5.477 420.56h92.184V143.24H5.477v277.32z"
451
+ }));
452
+ });
453
+
454
+ function _extends$3() {
455
+ _extends$3 = Object.assign || function (target) {
456
+ for (var i = 1; i < arguments.length; i++) {
457
+ var source = arguments[i];
458
+
459
+ for (var key in source) {
460
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
461
+ target[key] = source[key];
462
+ }
463
+ }
464
+ }
465
+
466
+ return target;
467
+ };
468
+
469
+ return _extends$3.apply(this, arguments);
470
+ }
471
+ var TelegramIcon = (function (_ref) {
472
+ var _ref$styles = _ref.styles,
473
+ props = _objectWithoutProperties(_ref, ["styles"]);
474
+
475
+ return React.createElement("svg", _extends$3({
476
+ xmlns: "http://www.w3.org/2000/svg",
477
+ viewBox: "0 0 512.004 512.004"
478
+ }, props), React.createElement("path", {
479
+ d: "M508.194 20.517c-4.43-4.96-11.42-6.29-17.21-3.76l-482 211a15.01 15.01 0 00-8.98 13.41 15.005 15.005 0 008.38 13.79l115.09 56.6 28.68 172.06c.93 6.53 6.06 11.78 12.74 12.73 4.8.69 9.57-1 12.87-4.4l90.86-90.86 129.66 92.62a15.02 15.02 0 0014.24 1.74 15.01 15.01 0 009.19-11.01l90-451c.89-4.47-.26-9.26-3.52-12.92zm-372.84 263.45l-84.75-41.68 334.82-146.57-250.07 188.25zm46.94 44.59l-13.95 69.75-15.05-90.3 183.97-138.49-150.88 151.39c-2.12 2.12-3.53 4.88-4.09 7.65zm9.13 107.3l15.74-78.67 36.71 26.22-52.45 52.45zm205.41 19.94l-176.73-126.23 252.47-253.31-75.74 379.54z"
480
+ }));
481
+ });
482
+
483
+ function _extends$4() {
484
+ _extends$4 = Object.assign || function (target) {
485
+ for (var i = 1; i < arguments.length; i++) {
486
+ var source = arguments[i];
487
+
488
+ for (var key in source) {
489
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
490
+ target[key] = source[key];
491
+ }
492
+ }
493
+ }
494
+
495
+ return target;
496
+ };
497
+
498
+ return _extends$4.apply(this, arguments);
499
+ }
500
+ var TwitterIcon = (function (_ref) {
501
+ var _ref$styles = _ref.styles,
502
+ props = _objectWithoutProperties(_ref, ["styles"]);
503
+
504
+ return React.createElement("svg", _extends$4({
505
+ xmlns: "http://www.w3.org/2000/svg",
506
+ viewBox: "0 0 612 612"
507
+ }, props), React.createElement("path", {
508
+ d: "M612 116.258a250.714 250.714 0 01-72.088 19.772c25.929-15.527 45.777-40.155 55.184-69.411-24.322 14.379-51.169 24.82-79.775 30.48-22.907-24.437-55.49-39.658-91.63-39.658-69.334 0-125.551 56.217-125.551 125.513 0 9.828 1.109 19.427 3.251 28.606-104.326-5.24-196.835-55.223-258.75-131.174-10.823 18.51-16.98 40.078-16.98 63.101 0 43.559 22.181 81.993 55.835 104.479a125.556 125.556 0 01-56.867-15.756v1.568c0 60.806 43.291 111.554 100.693 123.104-10.517 2.83-21.607 4.398-33.08 4.398-8.107 0-15.947-.803-23.634-2.333 15.985 49.907 62.336 86.199 117.253 87.194-42.947 33.654-97.099 53.655-155.916 53.655-10.134 0-20.116-.612-29.944-1.721 55.567 35.681 121.536 56.485 192.438 56.485 230.948 0 357.188-191.291 357.188-357.188l-.421-16.253c24.666-17.593 46.005-39.697 62.794-64.861z"
509
+ }));
510
+ });
511
+
512
+ function _extends$5() {
513
+ _extends$5 = Object.assign || function (target) {
514
+ for (var i = 1; i < arguments.length; i++) {
515
+ var source = arguments[i];
516
+
517
+ for (var key in source) {
518
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
519
+ target[key] = source[key];
520
+ }
521
+ }
522
+ }
523
+
524
+ return target;
525
+ };
526
+
527
+ return _extends$5.apply(this, arguments);
528
+ }
529
+ var WhatsAppIcon = (function (_ref) {
530
+ var _ref$styles = _ref.styles,
531
+ props = _objectWithoutProperties(_ref, ["styles"]);
532
+
533
+ return React.createElement("svg", _extends$5({
534
+ xmlns: "http://www.w3.org/2000/svg",
535
+ viewBox: "0 0 90 90"
536
+ }, props), React.createElement("path", {
537
+ d: "M90 43.841c0 24.213-19.779 43.841-44.182 43.841a44.256 44.256 0 01-21.357-5.455L0 90l7.975-23.522a43.38 43.38 0 01-6.34-22.637C1.635 19.628 21.416 0 45.818 0 70.223 0 90 19.628 90 43.841zM45.818 6.982c-20.484 0-37.146 16.535-37.146 36.859 0 8.065 2.629 15.534 7.076 21.61L11.107 79.14l14.275-4.537A37.122 37.122 0 0045.819 80.7c20.481 0 37.146-16.533 37.146-36.857S66.301 6.982 45.818 6.982zm22.311 46.956c-.273-.447-.994-.717-2.076-1.254-1.084-.537-6.41-3.138-7.4-3.495-.993-.358-1.717-.538-2.438.537-.721 1.076-2.797 3.495-3.43 4.212-.632.719-1.263.809-2.347.271-1.082-.537-4.571-1.673-8.708-5.333-3.219-2.848-5.393-6.364-6.025-7.441-.631-1.075-.066-1.656.475-2.191.488-.482 1.084-1.255 1.625-1.882.543-.628.723-1.075 1.082-1.793.363-.717.182-1.344-.09-1.883-.27-.537-2.438-5.825-3.34-7.977-.902-2.15-1.803-1.792-2.436-1.792-.631 0-1.354-.09-2.076-.09s-1.896.269-2.889 1.344c-.992 1.076-3.789 3.676-3.789 8.963 0 5.288 3.879 10.397 4.422 11.113.541.716 7.49 11.92 18.5 16.223C58.2 65.771 58.2 64.336 60.186 64.156c1.984-.179 6.406-2.599 7.312-5.107.9-2.512.9-4.663.631-5.111z"
538
+ }));
539
+ });
540
+
541
+ /**
542
+ * Returns a list of attributes (icon, name and url) of all configured share providers of the entry.
543
+ * The url provides a %{url} placeholder where the link can be inserted.
544
+ *
545
+ * @example
546
+ *
547
+ * const shareProviders = useShareProviders(options);
548
+ * shareProviders // =>
549
+ * [
550
+ * {
551
+ * icon: <FacebookSVGIcon />,
552
+ * name: 'Facebook',
553
+ * url: http://www.facebook.com/sharer/sharer.php?u=%{url}
554
+ * },
555
+ * {
556
+ * icon: <TwitterSVGIcon />,
557
+ * name: 'Twitter',
558
+ * url: https://twitter.com/intent/tweet?url=%{url}
559
+ * }
560
+ * ]
561
+ */
562
+
563
+ function useShareProviders(_ref) {
564
+ var isPhonePlatform = _ref.isPhonePlatform;
565
+ var config = useEntryStateConfig();
566
+ var entryMetadata = useEntryMetadata();
567
+ var shareProviders = entryMetadata ? entryMetadata.shareProviders : {};
568
+ var urlTemplates = config.shareUrlTemplates;
569
+ var sharing = {
570
+ email: {
571
+ icon: EmailIcon,
572
+ name: 'Mail',
573
+ url: urlTemplates.email
574
+ },
575
+ facebook: {
576
+ icon: FacebookIcon,
577
+ name: 'Facebook',
578
+ url: urlTemplates.facebook
579
+ },
580
+ linked_in: {
581
+ icon: LinkedInIcon,
582
+ name: 'LinkedIn',
583
+ url: urlTemplates.linked_in
584
+ },
585
+ telegram: {
586
+ icon: TelegramIcon,
587
+ name: 'Telegram',
588
+ url: urlTemplates.telegram
589
+ },
590
+ twitter: {
591
+ icon: TwitterIcon,
592
+ name: 'Twitter',
593
+ url: urlTemplates.twitter
594
+ },
595
+ whats_app: {
596
+ icon: WhatsAppIcon,
597
+ name: 'WhatsApp',
598
+ url: urlTemplates.whats_app
599
+ }
600
+ };
601
+ return useMemo(function () {
602
+ return activeShareProviders(shareProviders, isPhonePlatform).map(function (provider) {
603
+ var config = sharing[provider];
604
+ return {
605
+ name: config.name,
606
+ icon: config.icon,
607
+ url: config.url
608
+ };
609
+ });
610
+ }, [shareProviders, isPhonePlatform]);
611
+ }
612
+
613
+ function activeShareProviders(shareProvidersConfig, isPhonePlatform) {
614
+ var providers = filterShareProviders(shareProvidersConfig, isPhonePlatform);
615
+ return providers.filter(function (provider) {
616
+ return shareProvidersConfig[provider] !== false;
617
+ });
618
+ }
619
+
620
+ function filterShareProviders(shareProvidersConfig, isPhonePlatform) {
621
+ if (!isPhonePlatform) {
622
+ return Object.keys(shareProvidersConfig).filter(function (provider) {
623
+ return provider !== 'telegram' && provider !== 'whats_app';
624
+ });
625
+ }
626
+
627
+ return Object.keys(shareProvidersConfig);
628
+ }
629
+ /**
630
+ * Returns the share url of the entry.
631
+ *
632
+ * @example
633
+ *
634
+ * const shareUrl = useShareUrl();
635
+ * shareUrl // => "http://test.host/test"
636
+ */
637
+
638
+
639
+ function useShareUrl() {
640
+ var entryMetadata = useEntryMetadata();
641
+ var config = useEntryStateConfig();
642
+
643
+ if (entryMetadata) {
644
+ return entryMetadata.shareUrl ? entryMetadata.shareUrl : config.prettyUrl;
645
+ } else {
646
+ return config.shareUrl;
647
+ }
648
+ }
649
+
650
+ /**
651
+ * Returns a nested data structure representing the chapters, sections
652
+ * and content elements of the entry.
653
+ *
654
+ * @private
655
+ *
656
+ * @example
657
+ *
658
+ * const structure = useEntryStructure();
659
+ * structure // =>
660
+ * [
661
+ * {
662
+ * permaId: 5,
663
+ * title: 'Chapter 1',
664
+ * summary: 'An introductory chapter',
665
+ * sections: [
666
+ * {
667
+ * id: 1,
668
+ * permaId: 101,
669
+ * chapterId: 3,
670
+ * sectionIndex: 0,
671
+ * transition: 'scroll',
672
+ *
673
+ * // references to adjacent section objects
674
+ * previousSection: { ... },
675
+ * nextSection: { ... },
676
+ * }
677
+ * ],
678
+ * }
679
+ * ]
680
+ */
681
+
682
+ function useEntryStructure() {
683
+ var chapters = useChapters();
684
+ var sections = useEntryStateCollectionItems('sections');
685
+ return useMemo(function () {
686
+ var linkedSections = sections.map(function (section) {
687
+ return sectionData(section);
688
+ });
689
+ linkedSections.forEach(function (section, index) {
690
+ section.sectionIndex = index;
691
+ section.previousSection = linkedSections[index - 1];
692
+ section.nextSection = linkedSections[index + 1];
693
+ });
694
+ return chapters.map(function (chapter) {
695
+ return _objectSpread2(_objectSpread2({}, chapter), {}, {
696
+ sections: linkedSections.filter(function (item) {
697
+ return item.chapterId === chapter.id;
698
+ })
699
+ });
700
+ });
701
+ }, [chapters, sections]);
702
+ }
703
+ /**
704
+ * Returns a nested data structure representing the content elements
705
+ * of section.
706
+ *
707
+ * @param {Object} options
708
+ * @param {number} options.sectionPermaId
709
+ *
710
+ * @private
711
+ *
712
+ * @example
713
+ *
714
+ * const section = useSection({sectionPermaId: 4});
715
+ * section // =>
716
+ * {
717
+ * id: 100,
718
+ * permaId: 4,
719
+ * chapterId: 1,
720
+ * transition: 'scroll'
721
+ * }
722
+ */
723
+
724
+ function useSection(_ref) {
725
+ var sectionPermaId = _ref.sectionPermaId;
726
+ var section = useEntryStateCollectionItem('sections', sectionPermaId);
727
+ return sectionData(section);
728
+ }
729
+
730
+ function sectionData(section) {
731
+ return section && _objectSpread2({
732
+ permaId: section.permaId,
733
+ id: section.id,
734
+ chapterId: section.chapterId
735
+ }, section.configuration);
736
+ }
737
+
738
+ function useSectionContentElements(_ref2) {
739
+ var sectionId = _ref2.sectionId;
740
+ var filterBySectionId = useCallback(function (contentElement) {
741
+ return contentElement.sectionId === sectionId;
742
+ }, [sectionId]);
743
+ var contentElements = useEntryStateCollectionItems('contentElements', filterBySectionId);
744
+ return contentElements.map(function (item) {
745
+ return {
746
+ id: item.id,
747
+ permaId: item.permaId,
748
+ type: item.typeName,
749
+ position: item.configuration.position,
750
+ props: item.configuration
751
+ };
752
+ });
753
+ }
754
+ function useChapters() {
755
+ var chapters = useEntryStateCollectionItems('chapters');
756
+ var chapterSlugs = {};
757
+ return chapters.map(function (chapter) {
758
+ var chapterSlug = chapter.configuration.title;
759
+
760
+ if (chapterSlug) {
761
+ chapterSlug = slugify(chapterSlug, {
762
+ lower: true,
763
+ locale: 'de',
764
+ strict: true
765
+ });
766
+
767
+ if (chapterSlugs[chapterSlug]) {
768
+ chapterSlug = chapterSlug + '-' + chapter.permaId; //append permaId if chapter reference is not unique
769
+ }
770
+
771
+ chapterSlugs[chapterSlug] = chapter;
772
+ } else {
773
+ chapterSlug = 'chapter-' + chapter.permaId;
774
+ }
775
+
776
+ return {
777
+ id: chapter.id,
778
+ permaId: chapter.permaId,
779
+ title: chapter.configuration.title,
780
+ summary: chapter.configuration.summary,
781
+ chapterSlug: chapterSlug
782
+ };
783
+ });
784
+ }
785
+
786
+ function extendFile(collectionName, file, config) {
787
+ return addModelType(collectionName, expandUrls(collectionName, file, config.fileUrlTemplates), config.fileModelTypes);
788
+ }
789
+
790
+ function addModelType(collectionName, file, modelTypes) {
791
+ if (!file) {
792
+ return null;
793
+ }
794
+
795
+ if (!modelTypes[collectionName]) {
796
+ throw new Error("Could not find model type for collection name ".concat(collectionName));
797
+ }
798
+
799
+ return _objectSpread2(_objectSpread2({}, file), {}, {
800
+ modelType: modelTypes[collectionName]
801
+ });
802
+ }
803
+
804
+ function expandUrls(collectionName, file, urlTemplates) {
805
+ if (!file) {
806
+ return null;
807
+ }
808
+
809
+ if (!urlTemplates[collectionName]) {
810
+ throw new Error("No file url templates found for ".concat(collectionName));
811
+ }
812
+
813
+ var variants = file.variants || Object.keys(urlTemplates[collectionName]);
814
+ var urls = variants.reduce(function (result, variant) {
815
+ var url = getFileUrl(collectionName, file, variant, urlTemplates);
816
+
817
+ if (url) {
818
+ result[variant] = url;
819
+ }
820
+
821
+ return result;
822
+ }, {});
823
+ return _objectSpread2({
824
+ urls: urls
825
+ }, file);
826
+ }
827
+
828
+ function getFileUrl(collectionName, file, quality, urlTemplates) {
829
+ var templates = urlTemplates[collectionName];
830
+ var template = templates[quality];
831
+
832
+ if (template) {
833
+ return template.replace(':id_partition', idPartition(file.id)).replace(':basename', file.basename);
834
+ }
835
+ }
836
+
837
+ function idPartition(id) {
838
+ return partition(pad(id, 9));
839
+ }
840
+
841
+ function partition(string, separator) {
842
+ return string.replace(/./g, function (c, i, a) {
843
+ return i && (a.length - i) % 3 === 0 ? '/' + c : c;
844
+ });
845
+ }
846
+
847
+ function pad(string, size) {
848
+ return (Array(size).fill(0).join('') + string).slice(-size);
849
+ }
850
+
851
+ /**
852
+ * Look up a file by its collection and perma id.
853
+ *
854
+ * @param {Object} options
855
+ * @param {String} options.collectionName - Collection name of file type to look for (in camel case).
856
+ * @param {String} options.permaId - Perma id of file look up
857
+ *
858
+ * @example
859
+ * const imageFile = useFile({collectionName: 'imageFiles', permaId: 5});
860
+ * imageFile // =>
861
+ * {
862
+ * id: 102,
863
+ * permaId: 5,
864
+ * width: 1000,
865
+ * height: 500,
866
+ * urls: {
867
+ * large: 'https://...'
868
+ * },
869
+ * configuration: {
870
+ * alt: '...'
871
+ * }
872
+ * }
873
+ */
874
+
875
+ function useFile(_ref) {
876
+ var collectionName = _ref.collectionName,
877
+ permaId = _ref.permaId;
878
+ var file = useEntryStateCollectionItem(collectionName, permaId);
879
+ return extendFile(collectionName, file, useEntryStateConfig());
880
+ }
881
+
882
+ function useNestedFiles(_ref) {
883
+ var collectionName = _ref.collectionName,
884
+ parent = _ref.parent;
885
+ var config = useEntryStateConfig();
886
+ var files = useEntryStateCollectionItems(collectionName, function (file) {
887
+ return parent && file.parentFileId === parent.id && file.parentFileModelType === parent.modelType;
888
+ });
889
+ return files.map(function (file) {
890
+ return extendFile(collectionName, file, config);
891
+ });
892
+ }
893
+
894
+ /**
895
+ * Returns a string (comma-separated list) of copyrights of
896
+ * all images used in the entry.
897
+ * If none of the images has a rights attribute configured,
898
+ * it falls back to the default file rights of the entry's account,
899
+ * otherwise returns an empty string
900
+ *
901
+ * @example
902
+ *
903
+ * const fileRights = useFileRights();
904
+ * fileRights // => "author of image 1, author of image 2"
905
+ */
906
+
907
+ function useFileRights() {
908
+ var _config$defaultFileRi;
909
+
910
+ var config = useEntryStateConfig();
911
+ var imageFiles = useEntryStateCollectionItems('imageFiles');
912
+ var defaultFileRights = (_config$defaultFileRi = config.defaultFileRights) === null || _config$defaultFileRi === void 0 ? void 0 : _config$defaultFileRi.trim();
913
+ return Array.from(new Set(imageFiles.map(function (imageFile) {
914
+ var _imageFile$rights;
915
+
916
+ return ((_imageFile$rights = imageFile.rights) === null || _imageFile$rights === void 0 ? void 0 : _imageFile$rights.trim()) || defaultFileRights;
917
+ }))).filter(Boolean).join(', ');
918
+ }
919
+ /**
920
+ * Returns a nested data structure representing the legal info of the entry.
921
+ * Each legal info is separated into label and url to use in links.
922
+ * Both label and url can be blank, depending on the configuration.
923
+ *
924
+ * @example
925
+ *
926
+ * const legalInfo = useLegalInfo();
927
+ * legalInfo // =>
928
+ * {
929
+ * imprint: {
930
+ * label: '',
931
+ * url: ''
932
+ * },
933
+ * copyright: {
934
+ * label: '',
935
+ * url: ''
936
+ * },
937
+ * privacy: {
938
+ * label: '',
939
+ * url: ''
940
+ * }
941
+ * }
942
+ */
943
+
944
+ function useLegalInfo() {
945
+ var config = useEntryStateConfig();
946
+ return config.legalInfo;
947
+ }
948
+ /**
949
+ * Returns the credits string (rich text) of the entry.
950
+ *
951
+ * @example
952
+ *
953
+ * const credits = useCredits();
954
+ * credits // => "Credits: <a href="http://pageflow.com">pageflow.com</a>"
955
+ */
956
+
957
+ function useCredits() {
958
+ var entryMetadata = useEntryMetadata();
959
+ var credits = '';
960
+
961
+ if (entryMetadata) {
962
+ credits = entryMetadata.credits;
963
+ }
964
+
965
+ return credits;
966
+ }
967
+
968
+ function _arrayWithoutHoles(arr) {
969
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
970
+ }
971
+
972
+ function _iterableToArray(iter) {
973
+ if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
974
+ }
975
+
976
+ function _nonIterableSpread() {
977
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
978
+ }
979
+
980
+ function _toConsumableArray(arr) {
981
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
982
+ }
983
+
984
+ var qualities = ['medium', 'fullhd', '4k'];
985
+ function useAvailableQualities(file) {
986
+ if (!file) {
987
+ return [];
988
+ }
989
+
990
+ return ['auto'].concat(_toConsumableArray(qualities.filter(function (name) {
991
+ return file.variants.includes(name);
992
+ })));
993
+ }
994
+
995
+ /**
996
+ * Returns an object containing theme asset paths.
997
+ *
998
+ * @example
999
+ *
1000
+ * const theme = useTheme();
1001
+ * theme // =>
1002
+ * {
1003
+ * assets: {
1004
+ * logoDesktop: 'path/to/logoDesktop.svg',
1005
+ * logoMobile: 'path/to/logoMobile.svg'
1006
+ * },
1007
+ * options: {
1008
+ * // options passed to `themes.register` in `pageflow.rb` initializer
1009
+ * // with camleized keys.
1010
+ * }
1011
+ * }
1012
+ */
1013
+
1014
+ function useTheme() {
1015
+ var config = useEntryStateConfig();
1016
+ return config.theme;
1017
+ }
1018
+
1019
+ function updateContentElementConfiguration(_ref) {
1020
+ var dispatch = _ref.dispatch,
1021
+ permaId = _ref.permaId,
1022
+ configuration = _ref.configuration;
1023
+ updateConfiguration({
1024
+ dispatch: dispatch,
1025
+ name: 'contentElements',
1026
+ key: permaId,
1027
+ configuration: configuration
1028
+ });
1029
+ }
1030
+
1031
+ var LocaleContext = createContext$1('en');
1032
+ function setupI18n(_ref) {
1033
+ var defaultLocale = _ref.defaultLocale,
1034
+ locale = _ref.locale,
1035
+ translations = _ref.translations;
1036
+ I18n.defaultLocale = defaultLocale;
1037
+ I18n.locale = locale;
1038
+ I18n.translations = translations;
1039
+ }
1040
+ function LocaleProvider(_ref2) {
1041
+ var children = _ref2.children;
1042
+
1043
+ var _ref3 = useEntryMetadata() || {},
1044
+ locale = _ref3.locale;
1045
+
1046
+ return (
1047
+ /*#__PURE__*/
1048
+ React.createElement(LocaleContext.Provider, {
1049
+ value: locale
1050
+ }, children)
1051
+ );
1052
+ }
1053
+ function useLocale() {
1054
+ return useContext(LocaleContext);
1055
+ }
1056
+ /**
1057
+ * Use translations in frontend elements. Uses the configured locale
1058
+ * of the current entry by default. Note that only translation keys
1059
+ * from the `pageflow_scrolled.public` scope are universally
1060
+ * available.
1061
+ *
1062
+ * to render translations for inline editing controls in the editor
1063
+ * preview, you can pass `"ui"` as `locale` option and use
1064
+ * translations from the `pageflow_scrolled.inline_editing` scope.
1065
+ *
1066
+ * @param {Object} [options]
1067
+ * @param {string} [locale="entry"] -
1068
+ * Pass `"ui"` to use the locale of the editor interface instead.
1069
+ *
1070
+ * @example
1071
+ * const {t} = useI18n();
1072
+ * t('pageflow_scrolled.public.some.key')
1073
+ *
1074
+ * const {t} = useI18n({locale: 'ui'});
1075
+ * t('pageflow_scrolled.inline_editing.some.key')
1076
+ */
1077
+
1078
+ function useI18n() {
1079
+ var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
1080
+ scope = _ref4.locale;
1081
+
1082
+ var locale = useLocale();
1083
+ return {
1084
+ t: function t(key, options) {
1085
+ return I18n.t(key, _objectSpread2(_objectSpread2({}, options), {}, {
1086
+ locale: scope !== 'ui' && locale
1087
+ }));
1088
+ }
1089
+ };
1090
+ }
1091
+
1092
+ export { EntryStateProvider as E, LocaleProvider as L, _slicedToArray as _, _defineProperty as a, _objectWithoutProperties as b, useFileRights as c, useLegalInfo as d, useCredits as e, useShareProviders as f, useShareUrl as g, useTheme as h, useChapters as i, useEntryStructure as j, _objectSpread2 as k, useEntryMetadata as l, useNestedFiles as m, useFile as n, useSectionContentElements as o, _toConsumableArray as p, useAvailableQualities as q, useEntryStateDispatch as r, useSection as s, setupI18n as t, useI18n as u, useLocale as v, updateContentElementConfiguration as w };