import { browser } from 'pageflow/frontend'; import React, { useReducer, useMemo, useCallback, createContext as createContext$1, useContext, useState, useEffect } from 'react'; import I18n from 'i18n-js'; import { createContext, useContextSelector } from 'use-context-selector'; import { createSelectorCreator, defaultMemoize, createSelector } from 'reselect'; import slugify from 'slugify'; function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var PREFIX = 'PAGEFLOW_SCROLLED_COLLECTION'; var RESET = "".concat(PREFIX, "_RESET"); var ADD = "".concat(PREFIX, "_ADD"); var CHANGE = "".concat(PREFIX, "_CHANGE"); var PATCH_CONFIGURATION = "".concat(PREFIX, "_PATCH_CONFIGURATION"); var REMOVE = "".concat(PREFIX, "_REMOVE"); var SORT = "".concat(PREFIX, "_SORT"); function useCollections() { var seed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, keyAttribute = _ref.keyAttribute; return useReducer(reducer, Object.keys(seed).reduce(function (result, key) { result[key] = init(seed[key], keyAttribute); return result; }, {})); } function reducer(state, action) { var collectionName = action.payload.collectionName; var keyAttribute = action.payload.keyAttribute; switch (action.type) { case RESET: return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, init(action.payload.items, keyAttribute))); case ADD: return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, { order: action.payload.order, items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, action.payload.attributes[keyAttribute], action.payload.attributes)) })); case CHANGE: return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, { order: state[collectionName].order, items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, action.payload.attributes[keyAttribute], action.payload.attributes)) })); case PATCH_CONFIGURATION: var key = action.payload.key; return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, { order: state[collectionName].order, items: _objectSpread2(_objectSpread2({}, state[collectionName].items), {}, _defineProperty({}, key, _objectSpread2(_objectSpread2({}, state[collectionName].items[key]), {}, { configuration: _objectSpread2(_objectSpread2({}, state[collectionName].items[key].configuration), action.payload.configuration) }))) })); case REMOVE: var clonedItems = _objectSpread2({}, state[collectionName].items); delete clonedItems[action.payload.key]; return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, { order: action.payload.order, items: clonedItems })); case SORT: return _objectSpread2(_objectSpread2({}, state), {}, _defineProperty({}, collectionName, { order: action.payload.order, items: state[collectionName].items })); default: return state; } } function init(items) { var keyAttribute = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'id'; items = items.filter(function (item) { return item[keyAttribute]; }); return { order: items.map(function (item) { return item[keyAttribute]; }), items: items.reduce(function (result, item) { result[item[keyAttribute]] = item; return result; }, {}) }; } function updateConfiguration(_ref2) { var dispatch = _ref2.dispatch, name = _ref2.name, key = _ref2.key, configuration = _ref2.configuration; dispatch({ type: PATCH_CONFIGURATION, payload: { collectionName: name, key: key, configuration: configuration } }); } function getItem(state, collectionName, key) { if (state[collectionName]) { return state[collectionName].items[key]; } } function createItemsSelector(collectionName, filter) { if (filter) { var itemsSelector = createItemsSelector(collectionName); return createShallowEqualArraysSelector(function (collections) { return itemsSelector(collections).filter(filter); }, function (items) { return items; }); } return createSelector(function (collections) { return collections[collectionName]; }, function (collection) { if (collection) { var items = collection.items; return collection.order.map(function (key) { return items[key]; }); } else { return []; } }); } var createShallowEqualArraysSelector = createSelectorCreator(defaultMemoize, shallowEqualArrays); function shallowEqualArrays(a, b) { return a.length === b.length && a.every(function (item, index) { return item === b[index]; }); } var Context = createContext(); function EntryStateProvider(_ref) { var seed = _ref.seed, children = _ref.children; var _useCollections = useCollections(seed.collections, { keyAttribute: 'permaId' }), _useCollections2 = _slicedToArray(_useCollections, 2), collections = _useCollections2[0], dispatch = _useCollections2[1]; var value = useMemo(function () { return { entryState: { collections: collections, config: seed.config }, dispatch: dispatch }; }, [collections, dispatch, seed]); return /*#__PURE__*/React.createElement(Context.Provider, { value: value }, children); } function useEntryState() { var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (entryState) { return entryState; }; return useContextSelector(Context, function (value) { return selector(value.entryState); }); } function useEntryStateDispatch() { return useContextSelector(Context, function (value) { return value.dispatch; }); } function useEntryStateConfig() { return useEntryState(function (entryState) { return entryState.config; }); } function useEntryStateCollectionItem(collectionName, key) { return useEntryState(function (entryState) { return getItem(entryState.collections, collectionName, key); }); } function useEntryStateCollectionItems(collectionName, filter) { var itemsSelector = useMemo(function () { return createItemsSelector(collectionName, filter); }, [collectionName, filter]); return useEntryState(function (entryState) { return itemsSelector(entryState.collections); }); } /** * Returns data generated by a Ruby lambda registered server * side via `config.additional_frontend_seed_data.register`. * * @example * * const data = useAdditionalSeedData('someSeed'); */ function useAdditionalSeedData(name) { var config = useEntryStateConfig(); if (!config.additionalSeedData[name]) { throw new Error("Could not find additional seed data with name '".concat(name, "'.")); } return config.additionalSeedData[name]; } /** * Returns a nested data structure representing the metadata of the entry. * * @example * * const metaData = useEntryMetadata(); * metaData // => * { * id: 5, * locale: 'en', * shareProviders: {email: false, facebook: true}, * share_url: 'http://test.host/test', * credits: 'Credits: Pageflow' * } */ function useEntryMetadata() { var entries = useEntryStateCollectionItems('entries'); return useMemo(function () { return entries[0]; }, [entries]); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var EmailIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 612 612" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); function _extends$1() { _extends$1 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); } var FacebookIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends$1({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 430.113 430.114" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); function _extends$2() { _extends$2 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); } var LinkedInIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends$2({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 430.117 430.117" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); function _extends$3() { _extends$3 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); } var TelegramIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends$3({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512.004 512.004" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); function _extends$4() { _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); } var TwitterIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends$4({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 612 612" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); function _extends$5() { _extends$5 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$5.apply(this, arguments); } var WhatsAppIcon = (function (_ref) { var _ref$styles = _ref.styles, props = _objectWithoutProperties(_ref, ["styles"]); return /*#__PURE__*/React.createElement("svg", _extends$5({ xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 90 90" }, props), /*#__PURE__*/React.createElement("path", { 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" })); }); /** * Returns a list of attributes (icon, name and url) of all configured share providers of the entry. * The url provides a %{url} placeholder where the link can be inserted. * * @example * * const shareProviders = useShareProviders(options); * shareProviders // => * [ * { * icon: , * name: 'Facebook', * url: http://www.facebook.com/sharer/sharer.php?u=%{url} * }, * { * icon: , * name: 'Twitter', * url: https://twitter.com/intent/tweet?url=%{url} * } * ] */ function useShareProviders(_ref) { var isPhonePlatform = _ref.isPhonePlatform; var config = useEntryStateConfig(); var entryMetadata = useEntryMetadata(); var shareProviders = (entryMetadata === null || entryMetadata === void 0 ? void 0 : entryMetadata.shareProviders) || {}; var urlTemplates = config.shareUrlTemplates; return useMemo(function () { var sharing = { email: { icon: EmailIcon, name: 'Mail', url: urlTemplates.email }, facebook: { icon: FacebookIcon, name: 'Facebook', url: urlTemplates.facebook }, linked_in: { icon: LinkedInIcon, name: 'LinkedIn', url: urlTemplates.linked_in }, telegram: { icon: TelegramIcon, name: 'Telegram', url: urlTemplates.telegram }, twitter: { icon: TwitterIcon, name: 'Twitter', url: urlTemplates.twitter }, whats_app: { icon: WhatsAppIcon, name: 'WhatsApp', url: urlTemplates.whats_app } }; return activeShareProviders(shareProviders, isPhonePlatform).map(function (provider) { var config = sharing[provider]; return { name: config.name, icon: config.icon, url: config.url }; }); }, [shareProviders, isPhonePlatform, urlTemplates]); } function activeShareProviders(shareProvidersConfig, isPhonePlatform) { var providers = filterShareProviders(shareProvidersConfig, isPhonePlatform); return providers.filter(function (provider) { return shareProvidersConfig[provider] !== false; }); } function filterShareProviders(shareProvidersConfig, isPhonePlatform) { if (!isPhonePlatform) { return Object.keys(shareProvidersConfig).filter(function (provider) { return provider !== 'telegram' && provider !== 'whats_app'; }); } return Object.keys(shareProvidersConfig); } /** * Returns the share url of the entry. * * @example * * const shareUrl = useShareUrl(); * shareUrl // => "http://test.host/test" */ function useShareUrl() { var entryMetadata = useEntryMetadata(); var config = useEntryStateConfig(); if (entryMetadata) { return entryMetadata.shareUrl ? entryMetadata.shareUrl : config.prettyUrl; } else { return config.shareUrl; } } /** * Returns a nested data structure representing the chapters and sections * of the entry. * * @private * * @example * * const structure = useEntryStructure(); * structure // => * [ * { * permaId: 5, * title: 'Chapter 1', * summary: 'An introductory chapter', * sections: [ * { * id: 1, * permaId: 101, * chapterId: 3, * sectionIndex: 0, * transition: 'scroll', * * // references to parent chapter * chapter: { ... }, * * // references to adjacent section objects * previousSection: { ... }, * nextSection: { ... }, * } * ], * } * ] */ function useEntryStructure() { var chapters = useChapters(); var sections = useEntryStateCollectionItems('sections'); return useMemo(function () { var linkedSections = sections.map(function (section) { return sectionData(section); }); linkedSections.forEach(function (section, index) { section.sectionIndex = index; section.previousSection = linkedSections[index - 1]; section.nextSection = linkedSections[index + 1]; }); return chapters.map(function (chapter) { var chapterSections = linkedSections.filter(function (item) { return item.chapterId === chapter.id; }); chapterSections.forEach(function (section) { return section.chapter = chapter; }); return _objectSpread2(_objectSpread2({}, chapter), {}, { sections: chapterSections }); }); }, [chapters, sections]); } /** * Returns an array of sections each with a chapter property containing * data about the parent chapter. * * @private * * @example * * const sections = useSectionsWithChapter(); * sections // => * [ * { * id: 1, * permaId: 101, * chapterId: 3, * transition: 'scroll', * chapter: { * id: 3, * permaId: 5, * title: 'Chapter 1', * summary: 'An introductory chapter', * chapterSlug: 'chapter-1' * }, * } * ] */ function useSectionsWithChapter() { var chapters = useChapters(); var sections = useEntryStateCollectionItems('sections'); var chaptersById = useMemo(function () { return chapters.reduce(function (result, chapter) { result[chapter.id] = chapter; return result; }, {}); }, [chapters]); return useMemo(function () { return sections.map(function (section, sectionIndex) { return _objectSpread2(_objectSpread2({ sectionIndex: sectionIndex }, sectionData(section)), {}, { chapter: chaptersById[section.chapterId] }); }); }, [chaptersById, sections]); } /** * Returns a nested data structure representing the content elements * of section. * * @param {Object} options * @param {number} options.sectionPermaId * * @private * * @example * * const section = useSection({sectionPermaId: 4}); * section // => * { * id: 100, * permaId: 4, * chapterId: 1, * transition: 'scroll' * } */ function useSection(_ref) { var sectionPermaId = _ref.sectionPermaId; var section = useEntryStateCollectionItem('sections', sectionPermaId); return sectionData(section); } function sectionData(section) { return section && _objectSpread2({ permaId: section.permaId, id: section.id, chapterId: section.chapterId }, section.configuration); } function useSectionContentElements(_ref2) { var sectionId = _ref2.sectionId; var filterBySectionId = useCallback(function (contentElement) { return contentElement.sectionId === sectionId; }, [sectionId]); var contentElements = useEntryStateCollectionItems('contentElements', filterBySectionId); return contentElements.map(function (item) { return { id: item.id, permaId: item.permaId, type: item.typeName, position: item.configuration.position, props: item.configuration }; }); } function useChapter(_ref3) { var permaId = _ref3.permaId; var chapters = useChapters(); return useMemo(function () { return chapters.find(function (chapter) { return chapter.permaId === permaId; }); }, [chapters, permaId]); } function useChapters() { var chapters = useEntryStateCollectionItems('chapters'); return useMemo(function () { var chapterSlugs = {}; return chapters.map(function (chapter, index) { var chapterSlug = chapter.configuration.title; if (chapterSlug) { chapterSlug = slugify(chapterSlug, { lower: true, locale: 'de', strict: true }); if (chapterSlugs[chapterSlug]) { chapterSlug = chapterSlug + '-' + chapter.permaId; //append permaId if chapter reference is not unique } chapterSlugs[chapterSlug] = chapter; } else { chapterSlug = 'chapter-' + chapter.permaId; } return { id: chapter.id, permaId: chapter.permaId, index: index, title: chapter.configuration.title, summary: chapter.configuration.summary, chapterSlug: chapterSlug }; }); }, [chapters]); } function extendFile(collectionName, file, config) { return addModelType(collectionName, expandUrls(collectionName, file, config.fileUrlTemplates), config.fileModelTypes); } function addModelType(collectionName, file, modelTypes) { if (!file) { return null; } if (!modelTypes[collectionName]) { throw new Error("Could not find model type for collection name ".concat(collectionName)); } return _objectSpread2(_objectSpread2({}, file), {}, { modelType: modelTypes[collectionName] }); } function expandUrls(collectionName, file, urlTemplates) { if (!file) { return null; } if (!urlTemplates[collectionName]) { throw new Error("No file url templates found for ".concat(collectionName)); } var variants = file.variants || Object.keys(urlTemplates[collectionName]); var urls = variants.reduce(function (result, variant) { var url = getFileUrl(collectionName, file, variant, urlTemplates); if (url) { result[variant] = url; } return result; }, {}); return _objectSpread2({ urls: urls }, file); } function getFileUrl(collectionName, file, quality, urlTemplates) { var templates = urlTemplates[collectionName]; var template = templates[quality]; if (template) { return template.replace(':id_partition', idPartition(file.id)).replace(':basename', file.basename).replace(':extension', file.extension).replace(':pageflow_hls_qualities', function () { return hlsQualities(file); }); } } function idPartition(id) { return partition(pad(id, 9)); } function partition(string, separator) { return string.replace(/./g, function (c, i, a) { return i && (a.length - i) % 3 === 0 ? '/' + c : c; }); } function pad(string, size) { return (Array(size).fill(0).join('') + string).slice(-size); } function hlsQualities(file) { return ['low', 'medium', 'high', 'fullhd', '4k'].filter(function (quality) { return file.variants.includes(quality); }).join(','); } /** * Look up a file by its collection and perma id. * * @param {Object} options * @param {String} options.collectionName - Collection name of file type to look for (in camel case). * @param {String} options.permaId - Perma id of file look up * * @example * const imageFile = useFile({collectionName: 'imageFiles', permaId: 5}); * imageFile // => * { * id: 102, * permaId: 5, * width: 1000, * height: 500, * urls: { * large: 'https://...' * }, * configuration: { * alt: '...' * } * } */ function useFile(_ref) { var collectionName = _ref.collectionName, permaId = _ref.permaId; var file = useEntryStateCollectionItem(collectionName, permaId); return extendFile(collectionName, file, useEntryStateConfig()); } function useNestedFiles(_ref) { var collectionName = _ref.collectionName, parent = _ref.parent; var config = useEntryStateConfig(); var files = useEntryStateCollectionItems(collectionName, function (file) { return parent && file.parentFileId === parent.id && file.parentFileModelType === parent.modelType; }); return files.map(function (file) { return extendFile(collectionName, file, config); }); } function getFileUrlTemplateHost(seed, collectionName, variant) { var hlsUrlTemplate = seed.config.fileUrlTemplates[collectionName][variant]; return hlsUrlTemplate.split('//')[1].split('/')[0]; } /** * Returns a string (comma-separated list) of copyrights of * all images used in the entry. * If none of the images has a rights attribute configured, * it falls back to the default file rights of the entry's account, * otherwise returns an empty string * * @example * * const fileRights = useFileRights(); * fileRights // => "author of image 1, author of image 2" */ function useFileRights() { var _config$defaultFileRi; var config = useEntryStateConfig(); var imageFiles = useEntryStateCollectionItems('imageFiles'); var defaultFileRights = (_config$defaultFileRi = config.defaultFileRights) === null || _config$defaultFileRi === void 0 ? void 0 : _config$defaultFileRi.trim(); return Array.from(new Set(imageFiles.map(function (imageFile) { var _imageFile$rights; return ((_imageFile$rights = imageFile.rights) === null || _imageFile$rights === void 0 ? void 0 : _imageFile$rights.trim()) || defaultFileRights; }))).filter(Boolean).join(', '); } /** * Returns a nested data structure representing the legal info of the entry. * Each legal info is separated into label and url to use in links. * Both label and url can be blank, depending on the configuration. * * @example * * const legalInfo = useLegalInfo(); * legalInfo // => * { * imprint: { * label: '', * url: '' * }, * copyright: { * label: '', * url: '' * }, * privacy: { * label: '', * url: '' * } * } */ function useLegalInfo() { var config = useEntryStateConfig(); return config.legalInfo; } /** * Returns the credits string (rich text) of the entry. * * @example * * const credits = useCredits(); * credits // => "Credits: pageflow.com" */ function useCredits() { var entryMetadata = useEntryMetadata(); var credits = ''; if (entryMetadata) { credits = entryMetadata.credits; } return credits; } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } var qualities = ['medium', 'fullhd', '4k']; function useAvailableQualities(file) { if (!file) { return []; } return ['auto'].concat(_toConsumableArray(qualities.filter(function (name) { return file.variants.includes(name); }))); } /** * Returns an object containing theme asset paths. * * @example * * const theme = useTheme(); * theme // => * { * assets: { * logoDesktop: 'path/to/logoDesktop.svg', * logoMobile: 'path/to/logoMobile.svg' * }, * options: { * // options passed to `themes.register` in `pageflow.rb` initializer * // with camleized keys. * } * } */ function useTheme() { var config = useEntryStateConfig(); return config.theme; } function useWidget(_ref) { var role = _ref.role; var widgets = useEntryStateCollectionItems('widgets'); return useMemo(function () { return widgets.find(function (widget) { return widget.role === role && widget.typeName; }); }, [role, widgets]); } function updateContentElementConfiguration(_ref) { var dispatch = _ref.dispatch, permaId = _ref.permaId, configuration = _ref.configuration; updateConfiguration({ dispatch: dispatch, name: 'contentElements', key: permaId, configuration: configuration }); } var LocaleContext = createContext$1('en'); function setupI18n(_ref) { var defaultLocale = _ref.defaultLocale, locale = _ref.locale, translations = _ref.translations; I18n.defaultLocale = defaultLocale; I18n.locale = locale; I18n.translations = translations; } function LocaleProvider(_ref2) { var children = _ref2.children; var _ref3 = useEntryMetadata() || {}, locale = _ref3.locale; return /*#__PURE__*/React.createElement(LocaleContext.Provider, { value: locale }, children); } function useLocale() { return useContext(LocaleContext); } /** * Use translations in frontend elements. Uses the configured locale * of the current entry by default. Note that only translation keys * from the `pageflow_scrolled.public` scope are universally * available. * * to render translations for inline editing controls in the editor * preview, you can pass `"ui"` as `locale` option and use * translations from the `pageflow_scrolled.inline_editing` scope. * * @param {Object} [options] * @param {string} [locale="entry"] - * Pass `"ui"` to use the locale of the editor interface instead. * * @example * const {t} = useI18n(); * t('pageflow_scrolled.public.some.key') * * const {t} = useI18n({locale: 'ui'}); * t('pageflow_scrolled.inline_editing.some.key') */ function useI18n() { var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, scope = _ref4.locale; var locale = useLocale(); return { t: function t(key, options) { return I18n.t(key, _objectSpread2(_objectSpread2({}, options), {}, { locale: scope !== 'ui' && locale })); } }; } var BrowserFeaturesAvailableContext = createContext$1(); // Browser feature detection is not available during server side // rendering. To prevent mismatches during hydration, we keep features // disabled in the initial render. Since hydration only starts after // feature detection has finished, we can immediately re-render once // the provider has mounted. function BrowserFeaturesProvider(_ref) { var children = _ref.children; var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), isAvailable = _useState2[0], setIsAvailable = _useState2[1]; useEffect(function () { return setIsAvailable(true); }, []); return /*#__PURE__*/React.createElement(BrowserFeaturesAvailableContext.Provider, { value: isAvailable }, children); } function useBrowserFeature(name) { return useContext(BrowserFeaturesAvailableContext) && browser.has(name); } var PhonePlatformContext = React.createContext(false); export { useShareProviders as A, BrowserFeaturesProvider as B, useShareUrl as C, updateContentElementConfiguration as D, EntryStateProvider as E, _unsupportedIterableToArray as F, LocaleProvider as L, PhonePlatformContext as P, _objectWithoutProperties as _, _objectSpread2 as a, _defineProperty as b, _slicedToArray as c, useLocale as d, useLegalInfo as e, useTheme as f, useEntryMetadata as g, useNestedFiles as h, useFile as i, _toConsumableArray as j, useSectionContentElements as k, useAdditionalSeedData as l, useSectionsWithChapter as m, useBrowserFeature as n, useEntryStateDispatch as o, useSection as p, useChapter as q, useEntryStructure as r, useWidget as s, getFileUrlTemplateHost as t, useI18n as u, useAvailableQualities as v, setupI18n as w, useChapters as x, useCredits as y, useFileRights as z };