diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/js/dist/core-data.js --- a/wp/wp-includes/js/dist/core-data.js Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/js/dist/core-data.js Fri Sep 05 18:40:08 2025 +0200 @@ -1,10 +1,192 @@ -/******/ (function() { // webpackBootstrap +/******/ (() => { // webpackBootstrap +/******/ "use strict"; /******/ var __webpack_modules__ = ({ -/***/ 2167: -/***/ (function(module) { - -"use strict"; +/***/ 6689: +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ createUndoManager: () => (/* binding */ createUndoManager) +/* harmony export */ }); +/* harmony import */ var _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(923); +/* harmony import */ var _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0__); +/** + * WordPress dependencies + */ + + +/** @typedef {import('./types').HistoryRecord} HistoryRecord */ +/** @typedef {import('./types').HistoryChange} HistoryChange */ +/** @typedef {import('./types').HistoryChanges} HistoryChanges */ +/** @typedef {import('./types').UndoManager} UndoManager */ + +/** + * Merge changes for a single item into a record of changes. + * + * @param {Record< string, HistoryChange >} changes1 Previous changes + * @param {Record< string, HistoryChange >} changes2 NextChanges + * + * @return {Record< string, HistoryChange >} Merged changes + */ +function mergeHistoryChanges(changes1, changes2) { + /** + * @type {Record< string, HistoryChange >} + */ + const newChanges = { + ...changes1 + }; + Object.entries(changes2).forEach(([key, value]) => { + if (newChanges[key]) { + newChanges[key] = { + ...newChanges[key], + to: value.to + }; + } else { + newChanges[key] = value; + } + }); + return newChanges; +} + +/** + * Adds history changes for a single item into a record of changes. + * + * @param {HistoryRecord} record The record to merge into. + * @param {HistoryChanges} changes The changes to merge. + */ +const addHistoryChangesIntoRecord = (record, changes) => { + const existingChangesIndex = record?.findIndex(({ + id: recordIdentifier + }) => { + return typeof recordIdentifier === 'string' ? recordIdentifier === changes.id : _wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default()(recordIdentifier, changes.id); + }); + const nextRecord = [...record]; + if (existingChangesIndex !== -1) { + // If the edit is already in the stack leave the initial "from" value. + nextRecord[existingChangesIndex] = { + id: changes.id, + changes: mergeHistoryChanges(nextRecord[existingChangesIndex].changes, changes.changes) + }; + } else { + nextRecord.push(changes); + } + return nextRecord; +}; + +/** + * Creates an undo manager. + * + * @return {UndoManager} Undo manager. + */ +function createUndoManager() { + /** + * @type {HistoryRecord[]} + */ + let history = []; + /** + * @type {HistoryRecord} + */ + let stagedRecord = []; + /** + * @type {number} + */ + let offset = 0; + const dropPendingRedos = () => { + history = history.slice(0, offset || undefined); + offset = 0; + }; + const appendStagedRecordToLatestHistoryRecord = () => { + var _history$index; + const index = history.length === 0 ? 0 : history.length - 1; + let latestRecord = (_history$index = history[index]) !== null && _history$index !== void 0 ? _history$index : []; + stagedRecord.forEach(changes => { + latestRecord = addHistoryChangesIntoRecord(latestRecord, changes); + }); + stagedRecord = []; + history[index] = latestRecord; + }; + + /** + * Checks whether a record is empty. + * A record is considered empty if it the changes keep the same values. + * Also updates to function values are ignored. + * + * @param {HistoryRecord} record + * @return {boolean} Whether the record is empty. + */ + const isRecordEmpty = record => { + const filteredRecord = record.filter(({ + changes + }) => { + return Object.values(changes).some(({ + from, + to + }) => typeof from !== 'function' && typeof to !== 'function' && !_wordpress_is_shallow_equal__WEBPACK_IMPORTED_MODULE_0___default()(from, to)); + }); + return !filteredRecord.length; + }; + return { + /** + * Record changes into the history. + * + * @param {HistoryRecord=} record A record of changes to record. + * @param {boolean} isStaged Whether to immediately create an undo point or not. + */ + addRecord(record, isStaged = false) { + const isEmpty = !record || isRecordEmpty(record); + if (isStaged) { + if (isEmpty) { + return; + } + record.forEach(changes => { + stagedRecord = addHistoryChangesIntoRecord(stagedRecord, changes); + }); + } else { + dropPendingRedos(); + if (stagedRecord.length) { + appendStagedRecordToLatestHistoryRecord(); + } + if (isEmpty) { + return; + } + history.push(record); + } + }, + undo() { + if (stagedRecord.length) { + dropPendingRedos(); + appendStagedRecordToLatestHistoryRecord(); + } + const undoRecord = history[history.length - 1 + offset]; + if (!undoRecord) { + return; + } + offset -= 1; + return undoRecord; + }, + redo() { + const redoRecord = history[history.length + offset]; + if (!redoRecord) { + return; + } + offset += 1; + return redoRecord; + }, + hasUndo() { + return !!history[history.length - 1 + offset]; + }, + hasRedo() { + return !!history[history.length + offset]; + } + }; +} + + +/***/ }), + +/***/ 3249: +/***/ ((module) => { + function _typeof(obj) { @@ -316,171 +498,89 @@ /***/ }), -/***/ 9756: -/***/ (function(module) { - -/** - * Memize options object. - * - * @typedef MemizeOptions - * - * @property {number} [maxSize] Maximum size of the cache. - */ - -/** - * Internal cache entry. - * - * @typedef MemizeCacheNode - * - * @property {?MemizeCacheNode|undefined} [prev] Previous node. - * @property {?MemizeCacheNode|undefined} [next] Next node. - * @property {Array<*>} args Function arguments for cache - * entry. - * @property {*} val Function result. - */ - -/** - * Properties of the enhanced function for controlling cache. - * - * @typedef MemizeMemoizedFunction - * - * @property {()=>void} clear Clear the cache. - */ - -/** - * Accepts a function to be memoized, and returns a new memoized function, with - * optional options. - * - * @template {Function} F - * - * @param {F} fn Function to memoize. - * @param {MemizeOptions} [options] Options object. - * - * @return {F & MemizeMemoizedFunction} Memoized function. - */ -function memize( fn, options ) { - var size = 0; - - /** @type {?MemizeCacheNode|undefined} */ - var head; - - /** @type {?MemizeCacheNode|undefined} */ - var tail; - - options = options || {}; - - function memoized( /* ...args */ ) { - var node = head, - len = arguments.length, - args, i; - - searchCache: while ( node ) { - // Perform a shallow equality test to confirm that whether the node - // under test is a candidate for the arguments passed. Two arrays - // are shallowly equal if their length matches and each entry is - // strictly equal between the two sets. Avoid abstracting to a - // function which could incur an arguments leaking deoptimization. - - // Check whether node arguments match arguments length - if ( node.args.length !== arguments.length ) { - node = node.next; - continue; - } - - // Check whether node arguments match arguments values - for ( i = 0; i < len; i++ ) { - if ( node.args[ i ] !== arguments[ i ] ) { - node = node.next; - continue searchCache; - } - } - - // At this point we can assume we've found a match - - // Surface matched node to head if not already - if ( node !== head ) { - // As tail, shift to previous. Must only shift if not also - // head, since if both head and tail, there is no previous. - if ( node === tail ) { - tail = node.prev; - } - - // Adjust siblings to point to each other. If node was tail, - // this also handles new tail's empty `next` assignment. - /** @type {MemizeCacheNode} */ ( node.prev ).next = node.next; - if ( node.next ) { - node.next.prev = node.prev; - } - - node.next = head; - node.prev = null; - /** @type {MemizeCacheNode} */ ( head ).prev = node; - head = node; - } - - // Return immediately - return node.val; - } - - // No cached value found. Continue to insertion phase: - - // Create a copy of arguments (avoid leaking deoptimization) - args = new Array( len ); - for ( i = 0; i < len; i++ ) { - args[ i ] = arguments[ i ]; - } - - node = { - args: args, - - // Generate the result from original function - val: fn.apply( null, args ), - }; - - // Don't need to check whether node is already head, since it would - // have been returned above already if it was - - // Shift existing head down list - if ( head ) { - head.prev = node; - node.next = head; - } else { - // If no head, follows that there's no tail (at initial or reset) - tail = node; - } - - // Trim tail if we're reached max size and are pending cache insertion - if ( size === /** @type {MemizeOptions} */ ( options ).maxSize ) { - tail = /** @type {MemizeCacheNode} */ ( tail ).prev; - /** @type {MemizeCacheNode} */ ( tail ).next = null; - } else { - size++; - } - - head = node; - - return node.val; - } - - memoized.clear = function() { - head = null; - tail = null; - size = 0; - }; - - if ( false ) {} - - // Ignore reason: There's not a clear solution to create an intersection of - // the function with additional properties, where the goal is to retain the - // function signature of the incoming argument and add control properties - // on the return value. - - // @ts-ignore - return memoized; -} - -module.exports = memize; - +/***/ 7734: +/***/ ((module) => { + + + +// do not edit .js files directly - edit src/index.jst + + + var envHasBigInt64Array = typeof BigInt64Array !== 'undefined'; + + +module.exports = function equal(a, b) { + if (a === b) return true; + + if (a && b && typeof a == 'object' && typeof b == 'object') { + if (a.constructor !== b.constructor) return false; + + var length, i, keys; + if (Array.isArray(a)) { + length = a.length; + if (length != b.length) return false; + for (i = length; i-- !== 0;) + if (!equal(a[i], b[i])) return false; + return true; + } + + + if ((a instanceof Map) && (b instanceof Map)) { + if (a.size !== b.size) return false; + for (i of a.entries()) + if (!b.has(i[0])) return false; + for (i of a.entries()) + if (!equal(i[1], b.get(i[0]))) return false; + return true; + } + + if ((a instanceof Set) && (b instanceof Set)) { + if (a.size !== b.size) return false; + for (i of a.entries()) + if (!b.has(i[0])) return false; + return true; + } + + if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) { + length = a.length; + if (length != b.length) return false; + for (i = length; i-- !== 0;) + if (a[i] !== b[i]) return false; + return true; + } + + + if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags; + if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf(); + if (a.toString !== Object.prototype.toString) return a.toString() === b.toString(); + + keys = Object.keys(a); + length = keys.length; + if (length !== Object.keys(b).length) return false; + + for (i = length; i-- !== 0;) + if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; + + for (i = length; i-- !== 0;) { + var key = keys[i]; + + if (!equal(a[key], b[key])) return false; + } + + return true; + } + + // true if both NaN, false otherwise + return a!==a && b!==b; +}; + + +/***/ }), + +/***/ 923: +/***/ ((module) => { + +module.exports = window["wp"]["isShallowEqual"]; /***/ }) @@ -512,176 +612,208 @@ /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ -/******/ !function() { +/******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { +/******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? -/******/ function() { return module['default']; } : -/******/ function() { return module; }; +/******/ () => (module['default']) : +/******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; -/******/ }(); +/******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ -/******/ !function() { +/******/ (() => { /******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = function(exports, definition) { +/******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; -/******/ }(); +/******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ !function() { -/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -/******/ }(); +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ -/******/ !function() { +/******/ (() => { /******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { +/******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; -/******/ }(); +/******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be in strict mode. -!function() { -"use strict"; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { - "EntityProvider": function() { return /* reexport */ EntityProvider; }, - "__experimentalFetchLinkSuggestions": function() { return /* reexport */ _experimental_fetch_link_suggestions; }, - "__experimentalFetchUrlData": function() { return /* reexport */ _experimental_fetch_url_data; }, - "__experimentalUseEntityRecord": function() { return /* reexport */ __experimentalUseEntityRecord; }, - "__experimentalUseEntityRecords": function() { return /* reexport */ __experimentalUseEntityRecords; }, - "store": function() { return /* binding */ store; }, - "useEntityBlockEditor": function() { return /* reexport */ useEntityBlockEditor; }, - "useEntityId": function() { return /* reexport */ useEntityId; }, - "useEntityProp": function() { return /* reexport */ useEntityProp; } + EntityProvider: () => (/* reexport */ EntityProvider), + __experimentalFetchLinkSuggestions: () => (/* reexport */ _experimental_fetch_link_suggestions), + __experimentalFetchUrlData: () => (/* reexport */ _experimental_fetch_url_data), + __experimentalUseEntityRecord: () => (/* reexport */ __experimentalUseEntityRecord), + __experimentalUseEntityRecords: () => (/* reexport */ __experimentalUseEntityRecords), + __experimentalUseResourcePermissions: () => (/* reexport */ __experimentalUseResourcePermissions), + fetchBlockPatterns: () => (/* reexport */ fetchBlockPatterns), + store: () => (/* binding */ store), + useEntityBlockEditor: () => (/* reexport */ useEntityBlockEditor), + useEntityId: () => (/* reexport */ useEntityId), + useEntityProp: () => (/* reexport */ useEntityProp), + useEntityRecord: () => (/* reexport */ useEntityRecord), + useEntityRecords: () => (/* reexport */ useEntityRecords), + useResourcePermissions: () => (/* reexport */ useResourcePermissions) }); // NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/actions.js var build_module_actions_namespaceObject = {}; __webpack_require__.r(build_module_actions_namespaceObject); __webpack_require__.d(build_module_actions_namespaceObject, { - "__experimentalBatch": function() { return __experimentalBatch; }, - "__experimentalReceiveCurrentGlobalStylesId": function() { return __experimentalReceiveCurrentGlobalStylesId; }, - "__experimentalReceiveThemeBaseGlobalStyles": function() { return __experimentalReceiveThemeBaseGlobalStyles; }, - "__experimentalReceiveThemeGlobalStyleVariations": function() { return __experimentalReceiveThemeGlobalStyleVariations; }, - "__experimentalSaveSpecifiedEntityEdits": function() { return __experimentalSaveSpecifiedEntityEdits; }, - "__unstableCreateUndoLevel": function() { return __unstableCreateUndoLevel; }, - "addEntities": function() { return addEntities; }, - "deleteEntityRecord": function() { return deleteEntityRecord; }, - "editEntityRecord": function() { return editEntityRecord; }, - "receiveAutosaves": function() { return receiveAutosaves; }, - "receiveCurrentTheme": function() { return receiveCurrentTheme; }, - "receiveCurrentUser": function() { return receiveCurrentUser; }, - "receiveEmbedPreview": function() { return receiveEmbedPreview; }, - "receiveEntityRecords": function() { return receiveEntityRecords; }, - "receiveThemeSupports": function() { return receiveThemeSupports; }, - "receiveUploadPermissions": function() { return receiveUploadPermissions; }, - "receiveUserPermission": function() { return receiveUserPermission; }, - "receiveUserQuery": function() { return receiveUserQuery; }, - "redo": function() { return redo; }, - "saveEditedEntityRecord": function() { return saveEditedEntityRecord; }, - "saveEntityRecord": function() { return saveEntityRecord; }, - "undo": function() { return undo; } + __experimentalBatch: () => (__experimentalBatch), + __experimentalReceiveCurrentGlobalStylesId: () => (__experimentalReceiveCurrentGlobalStylesId), + __experimentalReceiveThemeBaseGlobalStyles: () => (__experimentalReceiveThemeBaseGlobalStyles), + __experimentalReceiveThemeGlobalStyleVariations: () => (__experimentalReceiveThemeGlobalStyleVariations), + __experimentalSaveSpecifiedEntityEdits: () => (__experimentalSaveSpecifiedEntityEdits), + __unstableCreateUndoLevel: () => (__unstableCreateUndoLevel), + addEntities: () => (addEntities), + deleteEntityRecord: () => (deleteEntityRecord), + editEntityRecord: () => (editEntityRecord), + receiveAutosaves: () => (receiveAutosaves), + receiveCurrentTheme: () => (receiveCurrentTheme), + receiveCurrentUser: () => (receiveCurrentUser), + receiveDefaultTemplateId: () => (receiveDefaultTemplateId), + receiveEmbedPreview: () => (receiveEmbedPreview), + receiveEntityRecords: () => (receiveEntityRecords), + receiveNavigationFallbackId: () => (receiveNavigationFallbackId), + receiveRevisions: () => (receiveRevisions), + receiveThemeGlobalStyleRevisions: () => (receiveThemeGlobalStyleRevisions), + receiveThemeSupports: () => (receiveThemeSupports), + receiveUploadPermissions: () => (receiveUploadPermissions), + receiveUserPermission: () => (receiveUserPermission), + receiveUserQuery: () => (receiveUserQuery), + redo: () => (redo), + saveEditedEntityRecord: () => (saveEditedEntityRecord), + saveEntityRecord: () => (saveEntityRecord), + undo: () => (undo) }); // NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/selectors.js var build_module_selectors_namespaceObject = {}; __webpack_require__.r(build_module_selectors_namespaceObject); __webpack_require__.d(build_module_selectors_namespaceObject, { - "__experimentalGetCurrentGlobalStylesId": function() { return __experimentalGetCurrentGlobalStylesId; }, - "__experimentalGetCurrentThemeBaseGlobalStyles": function() { return __experimentalGetCurrentThemeBaseGlobalStyles; }, - "__experimentalGetCurrentThemeGlobalStylesVariations": function() { return __experimentalGetCurrentThemeGlobalStylesVariations; }, - "__experimentalGetDirtyEntityRecords": function() { return __experimentalGetDirtyEntityRecords; }, - "__experimentalGetEntitiesBeingSaved": function() { return __experimentalGetEntitiesBeingSaved; }, - "__experimentalGetEntityRecordNoResolver": function() { return __experimentalGetEntityRecordNoResolver; }, - "__experimentalGetTemplateForLink": function() { return __experimentalGetTemplateForLink; }, - "canUser": function() { return canUser; }, - "canUserEditEntityRecord": function() { return canUserEditEntityRecord; }, - "getAuthors": function() { return getAuthors; }, - "getAutosave": function() { return getAutosave; }, - "getAutosaves": function() { return getAutosaves; }, - "getBlockPatternCategories": function() { return getBlockPatternCategories; }, - "getBlockPatterns": function() { return getBlockPatterns; }, - "getCurrentTheme": function() { return getCurrentTheme; }, - "getCurrentUser": function() { return getCurrentUser; }, - "getEditedEntityRecord": function() { return getEditedEntityRecord; }, - "getEmbedPreview": function() { return getEmbedPreview; }, - "getEntitiesByKind": function() { return getEntitiesByKind; }, - "getEntitiesConfig": function() { return getEntitiesConfig; }, - "getEntity": function() { return getEntity; }, - "getEntityConfig": function() { return getEntityConfig; }, - "getEntityRecord": function() { return getEntityRecord; }, - "getEntityRecordEdits": function() { return getEntityRecordEdits; }, - "getEntityRecordNonTransientEdits": function() { return getEntityRecordNonTransientEdits; }, - "getEntityRecords": function() { return getEntityRecords; }, - "getLastEntityDeleteError": function() { return getLastEntityDeleteError; }, - "getLastEntitySaveError": function() { return getLastEntitySaveError; }, - "getRawEntityRecord": function() { return getRawEntityRecord; }, - "getRedoEdit": function() { return getRedoEdit; }, - "getReferenceByDistinctEdits": function() { return getReferenceByDistinctEdits; }, - "getThemeSupports": function() { return getThemeSupports; }, - "getUndoEdit": function() { return getUndoEdit; }, - "getUserQueryResults": function() { return getUserQueryResults; }, - "hasEditsForEntityRecord": function() { return hasEditsForEntityRecord; }, - "hasEntityRecords": function() { return hasEntityRecords; }, - "hasFetchedAutosaves": function() { return hasFetchedAutosaves; }, - "hasRedo": function() { return hasRedo; }, - "hasUndo": function() { return hasUndo; }, - "isAutosavingEntityRecord": function() { return isAutosavingEntityRecord; }, - "isDeletingEntityRecord": function() { return isDeletingEntityRecord; }, - "isPreviewEmbedFallback": function() { return isPreviewEmbedFallback; }, - "isRequestingEmbedPreview": function() { return isRequestingEmbedPreview; }, - "isSavingEntityRecord": function() { return isSavingEntityRecord; } + __experimentalGetCurrentGlobalStylesId: () => (__experimentalGetCurrentGlobalStylesId), + __experimentalGetCurrentThemeBaseGlobalStyles: () => (__experimentalGetCurrentThemeBaseGlobalStyles), + __experimentalGetCurrentThemeGlobalStylesVariations: () => (__experimentalGetCurrentThemeGlobalStylesVariations), + __experimentalGetDirtyEntityRecords: () => (__experimentalGetDirtyEntityRecords), + __experimentalGetEntitiesBeingSaved: () => (__experimentalGetEntitiesBeingSaved), + __experimentalGetEntityRecordNoResolver: () => (__experimentalGetEntityRecordNoResolver), + __experimentalGetTemplateForLink: () => (__experimentalGetTemplateForLink), + canUser: () => (canUser), + canUserEditEntityRecord: () => (canUserEditEntityRecord), + getAuthors: () => (getAuthors), + getAutosave: () => (getAutosave), + getAutosaves: () => (getAutosaves), + getBlockPatternCategories: () => (getBlockPatternCategories), + getBlockPatterns: () => (getBlockPatterns), + getCurrentTheme: () => (getCurrentTheme), + getCurrentThemeGlobalStylesRevisions: () => (getCurrentThemeGlobalStylesRevisions), + getCurrentUser: () => (getCurrentUser), + getDefaultTemplateId: () => (getDefaultTemplateId), + getEditedEntityRecord: () => (getEditedEntityRecord), + getEmbedPreview: () => (getEmbedPreview), + getEntitiesByKind: () => (getEntitiesByKind), + getEntitiesConfig: () => (getEntitiesConfig), + getEntity: () => (getEntity), + getEntityConfig: () => (getEntityConfig), + getEntityRecord: () => (getEntityRecord), + getEntityRecordEdits: () => (getEntityRecordEdits), + getEntityRecordNonTransientEdits: () => (getEntityRecordNonTransientEdits), + getEntityRecords: () => (getEntityRecords), + getEntityRecordsTotalItems: () => (getEntityRecordsTotalItems), + getEntityRecordsTotalPages: () => (getEntityRecordsTotalPages), + getLastEntityDeleteError: () => (getLastEntityDeleteError), + getLastEntitySaveError: () => (getLastEntitySaveError), + getRawEntityRecord: () => (getRawEntityRecord), + getRedoEdit: () => (getRedoEdit), + getReferenceByDistinctEdits: () => (getReferenceByDistinctEdits), + getRevision: () => (getRevision), + getRevisions: () => (getRevisions), + getThemeSupports: () => (getThemeSupports), + getUndoEdit: () => (getUndoEdit), + getUserPatternCategories: () => (getUserPatternCategories), + getUserQueryResults: () => (getUserQueryResults), + hasEditsForEntityRecord: () => (hasEditsForEntityRecord), + hasEntityRecords: () => (hasEntityRecords), + hasFetchedAutosaves: () => (hasFetchedAutosaves), + hasRedo: () => (hasRedo), + hasUndo: () => (hasUndo), + isAutosavingEntityRecord: () => (isAutosavingEntityRecord), + isDeletingEntityRecord: () => (isDeletingEntityRecord), + isPreviewEmbedFallback: () => (isPreviewEmbedFallback), + isRequestingEmbedPreview: () => (isRequestingEmbedPreview), + isSavingEntityRecord: () => (isSavingEntityRecord) +}); + +// NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/private-selectors.js +var private_selectors_namespaceObject = {}; +__webpack_require__.r(private_selectors_namespaceObject); +__webpack_require__.d(private_selectors_namespaceObject, { + getBlockPatternsForPostType: () => (getBlockPatternsForPostType), + getNavigationFallbackId: () => (getNavigationFallbackId), + getUndoManager: () => (getUndoManager) }); // NAMESPACE OBJECT: ./node_modules/@wordpress/core-data/build-module/resolvers.js var resolvers_namespaceObject = {}; __webpack_require__.r(resolvers_namespaceObject); __webpack_require__.d(resolvers_namespaceObject, { - "__experimentalGetCurrentGlobalStylesId": function() { return resolvers_experimentalGetCurrentGlobalStylesId; }, - "__experimentalGetCurrentThemeBaseGlobalStyles": function() { return resolvers_experimentalGetCurrentThemeBaseGlobalStyles; }, - "__experimentalGetCurrentThemeGlobalStylesVariations": function() { return resolvers_experimentalGetCurrentThemeGlobalStylesVariations; }, - "__experimentalGetTemplateForLink": function() { return resolvers_experimentalGetTemplateForLink; }, - "canUser": function() { return resolvers_canUser; }, - "canUserEditEntityRecord": function() { return resolvers_canUserEditEntityRecord; }, - "getAuthors": function() { return resolvers_getAuthors; }, - "getAutosave": function() { return resolvers_getAutosave; }, - "getAutosaves": function() { return resolvers_getAutosaves; }, - "getBlockPatternCategories": function() { return resolvers_getBlockPatternCategories; }, - "getBlockPatterns": function() { return resolvers_getBlockPatterns; }, - "getCurrentTheme": function() { return resolvers_getCurrentTheme; }, - "getCurrentUser": function() { return resolvers_getCurrentUser; }, - "getEditedEntityRecord": function() { return resolvers_getEditedEntityRecord; }, - "getEmbedPreview": function() { return resolvers_getEmbedPreview; }, - "getEntityRecord": function() { return resolvers_getEntityRecord; }, - "getEntityRecords": function() { return resolvers_getEntityRecords; }, - "getRawEntityRecord": function() { return resolvers_getRawEntityRecord; }, - "getThemeSupports": function() { return resolvers_getThemeSupports; } + __experimentalGetCurrentGlobalStylesId: () => (resolvers_experimentalGetCurrentGlobalStylesId), + __experimentalGetCurrentThemeBaseGlobalStyles: () => (resolvers_experimentalGetCurrentThemeBaseGlobalStyles), + __experimentalGetCurrentThemeGlobalStylesVariations: () => (resolvers_experimentalGetCurrentThemeGlobalStylesVariations), + __experimentalGetTemplateForLink: () => (resolvers_experimentalGetTemplateForLink), + canUser: () => (resolvers_canUser), + canUserEditEntityRecord: () => (resolvers_canUserEditEntityRecord), + getAuthors: () => (resolvers_getAuthors), + getAutosave: () => (resolvers_getAutosave), + getAutosaves: () => (resolvers_getAutosaves), + getBlockPatternCategories: () => (resolvers_getBlockPatternCategories), + getBlockPatterns: () => (resolvers_getBlockPatterns), + getCurrentTheme: () => (resolvers_getCurrentTheme), + getCurrentThemeGlobalStylesRevisions: () => (resolvers_getCurrentThemeGlobalStylesRevisions), + getCurrentUser: () => (resolvers_getCurrentUser), + getDefaultTemplateId: () => (resolvers_getDefaultTemplateId), + getEditedEntityRecord: () => (resolvers_getEditedEntityRecord), + getEmbedPreview: () => (resolvers_getEmbedPreview), + getEntityRecord: () => (resolvers_getEntityRecord), + getEntityRecords: () => (resolvers_getEntityRecords), + getNavigationFallbackId: () => (resolvers_getNavigationFallbackId), + getRawEntityRecord: () => (resolvers_getRawEntityRecord), + getRevision: () => (resolvers_getRevision), + getRevisions: () => (resolvers_getRevisions), + getThemeSupports: () => (resolvers_getThemeSupports), + getUserPatternCategories: () => (resolvers_getUserPatternCategories) }); ;// CONCATENATED MODULE: external ["wp","data"] -var external_wp_data_namespaceObject = window["wp"]["data"]; -;// CONCATENATED MODULE: external "lodash" -var external_lodash_namespaceObject = window["lodash"]; -;// CONCATENATED MODULE: external ["wp","isShallowEqual"] -var external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"]; -var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject); +const external_wp_data_namespaceObject = window["wp"]["data"]; +// EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js +var es6 = __webpack_require__(7734); +var es6_default = /*#__PURE__*/__webpack_require__.n(es6); +;// CONCATENATED MODULE: external ["wp","compose"] +const external_wp_compose_namespaceObject = window["wp"]["compose"]; +// EXTERNAL MODULE: ./node_modules/@wordpress/undo-manager/build-module/index.js +var build_module = __webpack_require__(6689); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/if-matching-action.js /** @typedef {import('../types').AnyFunction} AnyFunction */ @@ -698,11 +830,9 @@ if (state === undefined || isMatch(action)) { return reducer(state, action); } - return state; }; - -/* harmony default export */ var if_matching_action = (ifMatchingAction); +/* harmony default export */ const if_matching_action = (ifMatchingAction); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/replace-action.js /** @typedef {import('../types').AnyFunction} AnyFunction */ @@ -718,14 +848,14 @@ const replaceAction = replacer => reducer => (state, action) => { return reducer(state, replacer(action)); }; - -/* harmony default export */ var replace_action = (replaceAction); +/* harmony default export */ const replace_action = (replaceAction); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/conservative-map-item.js /** * External dependencies */ + /** * Given the current and next item entity record, returns the minimally "modified" * result of the next item, preferring value references from the original item @@ -736,38 +866,33 @@ * * @return {Object} Minimally modified merged item. */ - function conservativeMapItem(item, nextItem) { // Return next item in its entirety if there is no original item. if (!item) { return nextItem; } - let hasChanges = false; const result = {}; - for (const key in nextItem) { - if ((0,external_lodash_namespaceObject.isEqual)(item[key], nextItem[key])) { + if (es6_default()(item[key], nextItem[key])) { result[key] = item[key]; } else { hasChanges = true; result[key] = nextItem[key]; } } - if (!hasChanges) { return item; - } // Only at this point, backfill properties from the original item which + } + + // Only at this point, backfill properties from the original item which // weren't explicitly set into the result above. This is an optimization // to allow `hasChanges` to return early. - - for (const key in item) { if (!result.hasOwnProperty(key)) { result[key] = item[key]; } } - return result; } @@ -782,48 +907,542 @@ * * @return {AnyFunction} Higher-order reducer. */ -const onSubKey = actionProperty => reducer => function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; +const onSubKey = actionProperty => reducer => (state = {}, action) => { // Retrieve subkey from action. Do not track if undefined; useful for cases // where reducer is scoped by action shape. const key = action[actionProperty]; - if (key === undefined) { return state; - } // Avoid updating state if unchanged. Note that this also accounts for a + } + + // Avoid updating state if unchanged. Note that this also accounts for a // reducer which returns undefined on a key which is not yet tracked. - - const nextKeyState = reducer(state[key], action); - if (nextKeyState === state[key]) { return state; } - - return { ...state, + return { + ...state, [key]: nextKeyState }; }; -/* harmony default export */ var on_sub_key = (onSubKey); +/* harmony default export */ const on_sub_key = (onSubKey); + +;// CONCATENATED MODULE: ./node_modules/tslib/tslib.es6.mjs +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + } + return __assign.apply(this, arguments); +} + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +} + +function __decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +} + +function __param(paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +} + +function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; +}; + +function __runInitializers(thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; +}; + +function __propKey(x) { + return typeof x === "symbol" ? x : "".concat(x); +}; + +function __setFunctionName(f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); +}; + +function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); +} + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +var __createBinding = Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); + +function __exportStar(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); +} + +function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); +} + +function __read(o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; +} + +/** @deprecated */ +function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; +} + +/** @deprecated */ +function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +} + +function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncDelegator(o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; + +var __setModuleDefault = Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}; + +function __importStar(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +} + +function __importDefault(mod) { + return (mod && mod.__esModule) ? mod : { default: mod }; +} + +function __classPrivateFieldGet(receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +} + +function __classPrivateFieldSet(receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +} + +function __classPrivateFieldIn(state, receiver) { + if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); + return typeof state === "function" ? receiver === state : state.has(receiver); +} + +function __addDisposableResource(env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; +} + +var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +function __disposeResources(env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + function next() { + while (env.stack.length) { + var rec = env.stack.pop(); + try { + var result = rec.dispose && rec.dispose.call(rec.value); + if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + catch (e) { + fail(e); + } + } + if (env.hasError) throw env.error; + } + return next(); +} + +/* harmony default export */ const tslib_es6 = ({ + __extends, + __assign, + __rest, + __decorate, + __param, + __metadata, + __awaiter, + __generator, + __createBinding, + __exportStar, + __values, + __read, + __spread, + __spreadArrays, + __spreadArray, + __await, + __asyncGenerator, + __asyncDelegator, + __asyncValues, + __makeTemplateObject, + __importStar, + __importDefault, + __classPrivateFieldGet, + __classPrivateFieldSet, + __classPrivateFieldIn, + __addDisposableResource, + __disposeResources, +}); + +;// CONCATENATED MODULE: ./node_modules/lower-case/dist.es2015/index.js +/** + * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt + */ +var SUPPORTED_LOCALE = { + tr: { + regexp: /\u0130|\u0049|\u0049\u0307/g, + map: { + İ: "\u0069", + I: "\u0131", + İ: "\u0069", + }, + }, + az: { + regexp: /\u0130/g, + map: { + İ: "\u0069", + I: "\u0131", + İ: "\u0069", + }, + }, + lt: { + regexp: /\u0049|\u004A|\u012E|\u00CC|\u00CD|\u0128/g, + map: { + I: "\u0069\u0307", + J: "\u006A\u0307", + Į: "\u012F\u0307", + Ì: "\u0069\u0307\u0300", + Í: "\u0069\u0307\u0301", + Ĩ: "\u0069\u0307\u0303", + }, + }, +}; +/** + * Localized lower case. + */ +function localeLowerCase(str, locale) { + var lang = SUPPORTED_LOCALE[locale.toLowerCase()]; + if (lang) + return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; })); + return lowerCase(str); +} +/** + * Lower case as a function. + */ +function lowerCase(str) { + return str.toLowerCase(); +} + +;// CONCATENATED MODULE: ./node_modules/no-case/dist.es2015/index.js + +// Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case"). +var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g]; +// Remove all non-word characters. +var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi; +/** + * Normalize the string into something other libraries can manipulate easier. + */ +function noCase(input, options) { + if (options === void 0) { options = {}; } + var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d; + var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0"); + var start = 0; + var end = result.length; + // Trim the delimiter from around the output string. + while (result.charAt(start) === "\0") + start++; + while (result.charAt(end - 1) === "\0") + end--; + // Transform each token independently. + return result.slice(start, end).split("\0").map(transform).join(delimiter); +} +/** + * Replace `re` in the input string with the replacement value. + */ +function replace(input, re, value) { + if (re instanceof RegExp) + return input.replace(re, value); + return re.reduce(function (input, re) { return input.replace(re, value); }, input); +} + +;// CONCATENATED MODULE: ./node_modules/upper-case-first/dist.es2015/index.js +/** + * Upper case the first character of an input string. + */ +function upperCaseFirst(input) { + return input.charAt(0).toUpperCase() + input.substr(1); +} + +;// CONCATENATED MODULE: ./node_modules/capital-case/dist.es2015/index.js + + + +function capitalCaseTransform(input) { + return upperCaseFirst(input.toLowerCase()); +} +function capitalCase(input, options) { + if (options === void 0) { options = {}; } + return noCase(input, __assign({ delimiter: " ", transform: capitalCaseTransform }, options)); +} + +;// CONCATENATED MODULE: ./node_modules/pascal-case/dist.es2015/index.js + + +function pascalCaseTransform(input, index) { + var firstChar = input.charAt(0); + var lowerChars = input.substr(1).toLowerCase(); + if (index > 0 && firstChar >= "0" && firstChar <= "9") { + return "_" + firstChar + lowerChars; + } + return "" + firstChar.toUpperCase() + lowerChars; +} +function dist_es2015_pascalCaseTransformMerge(input) { + return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase(); +} +function pascalCase(input, options) { + if (options === void 0) { options = {}; } + return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options)); +} ;// CONCATENATED MODULE: external ["wp","apiFetch"] -var external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; +const external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; var external_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_wp_apiFetch_namespaceObject); ;// CONCATENATED MODULE: external ["wp","i18n"] -var external_wp_i18n_namespaceObject = window["wp"]["i18n"]; +const external_wp_i18n_namespaceObject = window["wp"]["i18n"]; +;// CONCATENATED MODULE: external ["wp","richText"] +const external_wp_richText_namespaceObject = window["wp"]["richText"]; +;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/native.js +const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); +/* harmony default export */ const esm_browser_native = ({ + randomUUID +}); ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/rng.js // Unique ID creation requires a high quality random # generator. In the browser we therefore // require the crypto API and do not support built-in fallback to lower quality random number // generators (like Math.random()). -var getRandomValues; -var rnds8 = new Uint8Array(16); +let getRandomValues; +const rnds8 = new Uint8Array(16); function rng() { // lazy load so that environments that need to polyfill have a chance to do so if (!getRandomValues) { - // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, - // find the complete implementation of crypto (msCrypto) on IE11. - getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto); + // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. + getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); if (!getRandomValues) { throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); @@ -832,16 +1451,6 @@ return getRandomValues(rnds8); } -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/regex.js -/* harmony default export */ var regex = (/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i); -;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/validate.js - - -function validate(uuid) { - return typeof uuid === 'string' && regex.test(uuid); -} - -/* harmony default export */ var esm_browser_validate = (validate); ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/stringify.js /** @@ -849,37 +1458,45 @@ * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ -var byteToHex = []; - -for (var i = 0; i < 256; ++i) { - byteToHex.push((i + 0x100).toString(16).substr(1)); -} - -function stringify(arr) { - var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).slice(1)); +} + +function unsafeStringify(arr, offset = 0) { // Note: Be careful editing this code! It's been tuned for performance // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 - var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; +} + +function stringify(arr, offset = 0) { + const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one // of the following: // - One or more input array values don't map to a hex octet (leading to // "undefined" in the uuid) // - Invalid input values for the RFC `version` or `variant` fields - if (!esm_browser_validate(uuid)) { + if (!validate(uuid)) { throw TypeError('Stringified UUID is invalid'); } return uuid; } -/* harmony default export */ var esm_browser_stringify = (stringify); +/* harmony default export */ const esm_browser_stringify = ((/* unused pure expression or super */ null && (stringify))); ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/v4.js + function v4(options, buf, offset) { + if (esm_browser_native.randomUUID && !buf && !options) { + return esm_browser_native.randomUUID(); + } + options = options || {}; - var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = rnds[6] & 0x0f | 0x40; rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided @@ -887,43 +1504,110 @@ if (buf) { offset = offset || 0; - for (var i = 0; i < 16; ++i) { + for (let i = 0; i < 16; ++i) { buf[offset + i] = rnds[i]; } return buf; } - return esm_browser_stringify(rnds); -} - -/* harmony default export */ var esm_browser_v4 = (v4); + return unsafeStringify(rnds); +} + +/* harmony default export */ const esm_browser_v4 = (v4); ;// CONCATENATED MODULE: external ["wp","url"] -var external_wp_url_namespaceObject = window["wp"]["url"]; +const external_wp_url_namespaceObject = window["wp"]["url"]; ;// CONCATENATED MODULE: external ["wp","deprecated"] -var external_wp_deprecated_namespaceObject = window["wp"]["deprecated"]; +const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"]; var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject); +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/set-nested-value.js +/** + * Sets the value at path of object. + * If a portion of path doesn’t exist, it’s created. + * Arrays are created for missing index properties while objects are created + * for all other missing properties. + * + * Path is specified as either: + * - a string of properties, separated by dots, for example: "x.y". + * - an array of properties, for example `[ 'x', 'y' ]`. + * + * This function intentionally mutates the input object. + * + * Inspired by _.set(). + * + * @see https://lodash.com/docs/4.17.15#set + * + * @todo Needs to be deduplicated with its copy in `@wordpress/edit-site`. + * + * @param {Object} object Object to modify + * @param {Array|string} path Path of the property to set. + * @param {*} value Value to set. + */ +function setNestedValue(object, path, value) { + if (!object || typeof object !== 'object') { + return object; + } + const normalizedPath = Array.isArray(path) ? path : path.split('.'); + normalizedPath.reduce((acc, key, idx) => { + if (acc[key] === undefined) { + if (Number.isInteger(normalizedPath[idx + 1])) { + acc[key] = []; + } else { + acc[key] = {}; + } + } + if (idx === normalizedPath.length - 1) { + acc[key] = value; + } + return acc[key]; + }, object); + return object; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/get-nested-value.js +/** + * Helper util to return a value from a certain path of the object. + * Path is specified as either: + * - a string of properties, separated by dots, for example: "x.y". + * - an array of properties, for example `[ 'x', 'y' ]`. + * You can also specify a default value in case the result is nullish. + * + * @param {Object} object Input object. + * @param {string|Array} path Path to the object property. + * @param {*} defaultValue Default value if the value at the specified path is undefined. + * @return {*} Value of the object property at the specified path. + */ +function getNestedValue(object, path, defaultValue) { + if (!object || typeof object !== 'object' || typeof path !== 'string' && !Array.isArray(path)) { + return object; + } + const normalizedPath = Array.isArray(path) ? path : path.split('.'); + let value = object; + normalizedPath.forEach(fieldName => { + value = value?.[fieldName]; + }); + return value !== undefined ? value : defaultValue; +} + ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/actions.js /** - * External dependencies - */ - -/** * Returns an action object used in signalling that items have been received. * * @param {Array} items Items received. * @param {?Object} edits Optional edits to reset. + * @param {?Object} meta Meta information about pagination. * * @return {Object} Action object. */ - -function receiveItems(items, edits) { +function receiveItems(items, edits, meta) { return { type: 'RECEIVE_ITEMS', - items: (0,external_lodash_namespaceObject.castArray)(items), - persistedEdits: edits + items: Array.isArray(items) ? items : [items], + persistedEdits: edits, + meta }; } + /** * Returns an action object used in signalling that entity records have been * deleted and they need to be removed from entities state. @@ -934,17 +1618,16 @@ * @param {boolean} invalidateCache Controls whether we want to invalidate the cache. * @return {Object} Action object. */ - -function removeItems(kind, name, records) { - let invalidateCache = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; +function removeItems(kind, name, records, invalidateCache = false) { return { type: 'REMOVE_ITEMS', - itemIds: (0,external_lodash_namespaceObject.castArray)(records), + itemIds: Array.isArray(records) ? records : [records], kind, name, invalidateCache }; } + /** * Returns an action object used in signalling that queried data has been * received. @@ -952,24 +1635,19 @@ * @param {Array} items Queried items received. * @param {?Object} query Optional query object. * @param {?Object} edits Optional edits to reset. + * @param {?Object} meta Meta information about pagination. * * @return {Object} Action object. */ - -function receiveQueriedItems(items) { - let query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let edits = arguments.length > 2 ? arguments[2] : undefined; - return { ...receiveItems(items, edits), +function receiveQueriedItems(items, query = {}, edits, meta) { + return { + ...receiveItems(items, edits, meta), query }; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/batch/default-processor.js /** - * External dependencies - */ - -/** * WordPress dependencies */ @@ -980,18 +1658,25 @@ * * @type {number?} */ - let maxItems = null; +function chunk(arr, chunkSize) { + const tmp = [...arr]; + const cache = []; + while (tmp.length) { + cache.push(tmp.splice(0, chunkSize)); + } + return cache; +} + /** * Default batch processor. Sends its input requests to /batch/v1. * * @param {Array} requests List of API requests to perform at once. * * @return {Promise} Promise that resolves to a list of objects containing - * either `output` (if that request was succesful) or `error` + * either `output` (if that request was successful) or `error` * (if not ). */ - async function defaultProcessor(requests) { if (maxItems === null) { const preflightResponse = await external_wp_apiFetch_default()({ @@ -1000,10 +1685,10 @@ }); maxItems = preflightResponse.endpoints[0].args.requests.maxItems; } - - const results = []; // @ts-ignore We would have crashed or never gotten to this point if we hadn't received the maxItems count. - - for (const batchRequests of (0,external_lodash_namespaceObject.chunk)(requests, maxItems)) { + const results = []; + + // @ts-ignore We would have crashed or never gotten to this point if we hadn't received the maxItems count. + for (const batchRequests of chunk(requests, maxItems)) { const batchResponse = await external_wp_apiFetch_default()({ path: '/batch/v1', method: 'POST', @@ -1019,37 +1704,28 @@ } }); let batchResults; - if (batchResponse.failed) { batchResults = batchResponse.responses.map(response => ({ - error: response === null || response === void 0 ? void 0 : response.body + error: response?.body })); } else { batchResults = batchResponse.responses.map(response => { const result = {}; - if (response.status >= 200 && response.status < 300) { result.output = response.body; } else { result.error = response.body; } - return result; }); } - results.push(...batchResults); } - return results; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/batch/create-batch.js /** - * External dependencies - */ - -/** * Internal dependencies */ @@ -1087,12 +1763,9 @@ * resolves to an array of objects containing * either `output` or `error`. */ - -function createBatch() { - let processor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultProcessor; +function createBatch(processor = defaultProcessor) { let lastId = 0; /** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */ - let queue = []; const pending = new ObservableSet(); return { @@ -1125,7 +1798,6 @@ add(inputOrThunk) { const id = ++lastId; pending.add(id); - const add = input => new Promise((resolve, reject) => { queue.push({ input, @@ -1134,16 +1806,13 @@ }); pending.delete(id); }); - - if ((0,external_lodash_namespaceObject.isFunction)(inputOrThunk)) { + if (typeof inputOrThunk === 'function') { return Promise.resolve(inputOrThunk(add)).finally(() => { pending.delete(id); }); } - return add(inputOrThunk); }, - /** * Runs the batch. This calls `batchProcessor` and resolves or rejects * all promises returned by `add()`. @@ -1162,17 +1831,11 @@ }); }); } - let results; - try { - results = await processor(queue.map(_ref => { - let { - input - } = _ref; - return input; - })); - + results = await processor(queue.map(({ + input + }) => input)); if (results.length !== queue.length) { throw new Error('run: Array returned by processor must be same size as input array.'); } @@ -1182,69 +1845,48 @@ } of queue) { reject(error); } - throw error; } - let isSuccess = true; - - for (const pair of (0,external_lodash_namespaceObject.zip)(results, queue)) { - /** @type {{error?: unknown, output?: unknown}} */ - const result = pair[0]; - /** @type {{resolve: (value: any) => void; reject: (error: any) => void} | undefined} */ - - const queueItem = pair[1]; - - if (result !== null && result !== void 0 && result.error) { - queueItem === null || queueItem === void 0 ? void 0 : queueItem.reject(result.error); + results.forEach((result, key) => { + const queueItem = queue[key]; + if (result?.error) { + queueItem?.reject(result.error); isSuccess = false; } else { var _result$output; - - queueItem === null || queueItem === void 0 ? void 0 : queueItem.resolve((_result$output = result === null || result === void 0 ? void 0 : result.output) !== null && _result$output !== void 0 ? _result$output : result); + queueItem?.resolve((_result$output = result?.output) !== null && _result$output !== void 0 ? _result$output : result); } - } - + }); queue = []; return isSuccess; } - }; } - class ObservableSet { - constructor() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - + constructor(...args) { this.set = new Set(...args); this.subscribers = new Set(); } - get size() { return this.set.size; } - add(value) { this.set.add(value); this.subscribers.forEach(subscriber => subscriber()); return this; } - delete(value) { const isSuccess = this.set.delete(value); this.subscribers.forEach(subscriber => subscriber()); return isSuccess; } - subscribe(subscriber) { this.subscribers.add(subscriber); return () => { this.subscribers.delete(subscriber); }; } - } ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/name.js @@ -1262,6 +1904,7 @@ */ + /** * WordPress dependencies */ @@ -1277,36 +1920,44 @@ + + /** * Returns an action object used in signalling that authors have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} queryID Query ID. * @param {Array|Object} users Users received. * * @return {Object} Action object. */ - function receiveUserQuery(queryID, users) { return { type: 'RECEIVE_USER_QUERY', - users: (0,external_lodash_namespaceObject.castArray)(users), + users: Array.isArray(users) ? users : [users], queryID }; } + /** * Returns an action used in signalling that the current user has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {Object} currentUser Current user object. * * @return {Object} Action object. */ - function receiveCurrentUser(currentUser) { return { type: 'RECEIVE_CURRENT_USER', currentUser }; } + /** * Returns an action object used in adding new entities. * @@ -1314,13 +1965,13 @@ * * @return {Object} Action object. */ - function addEntities(entities) { return { type: 'ADD_ENTITIES', entities }; } + /** * Returns an action object used in signalling that entity records have been received. * @@ -1330,72 +1981,77 @@ * @param {?Object} query Query Object. * @param {?boolean} invalidateCache Should invalidate query caches. * @param {?Object} edits Edits to reset. + * @param {?Object} meta Meta information about pagination. * @return {Object} Action object. */ - -function receiveEntityRecords(kind, name, records, query) { - let invalidateCache = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; - let edits = arguments.length > 5 ? arguments[5] : undefined; - +function receiveEntityRecords(kind, name, records, query, invalidateCache = false, edits, meta) { // Auto drafts should not have titles, but some plugins rely on them so we can't filter this // on the server. if (kind === 'postType') { - records = (0,external_lodash_namespaceObject.castArray)(records).map(record => record.status === 'auto-draft' ? { ...record, + records = (Array.isArray(records) ? records : [records]).map(record => record.status === 'auto-draft' ? { + ...record, title: '' } : record); } - let action; - if (query) { - action = receiveQueriedItems(records, query, edits); + action = receiveQueriedItems(records, query, edits, meta); } else { - action = receiveItems(records, edits); - } - - return { ...action, + action = receiveItems(records, edits, meta); + } + return { + ...action, kind, name, invalidateCache }; } + /** * Returns an action object used in signalling that the current theme has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {Object} currentTheme The current theme. * * @return {Object} Action object. */ - function receiveCurrentTheme(currentTheme) { return { type: 'RECEIVE_CURRENT_THEME', currentTheme }; } + /** * Returns an action object used in signalling that the current global styles id has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} currentGlobalStylesId The current global styles id. * * @return {Object} Action object. */ - function __experimentalReceiveCurrentGlobalStylesId(currentGlobalStylesId) { return { type: 'RECEIVE_CURRENT_GLOBAL_STYLES_ID', id: currentGlobalStylesId }; } + /** * Returns an action object used in signalling that the theme base global styles have been received + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} stylesheet The theme's identifier * @param {Object} globalStyles The global styles object. * * @return {Object} Action object. */ - function __experimentalReceiveThemeBaseGlobalStyles(stylesheet, globalStyles) { return { type: 'RECEIVE_THEME_GLOBAL_STYLES', @@ -1403,15 +2059,18 @@ globalStyles }; } + /** * Returns an action object used in signalling that the theme global styles variations have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} stylesheet The theme's identifier * @param {Array} variations The global styles variations. * * @return {Object} Action object. */ - function __experimentalReceiveThemeGlobalStyleVariations(stylesheet, variations) { return { type: 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS', @@ -1419,6 +2078,7 @@ variations }; } + /** * Returns an action object used in signalling that the index has been received. * @@ -1426,7 +2086,6 @@ * * @return {Object} Action object. */ - function receiveThemeSupports() { external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeSupports", { since: '5.9' @@ -1435,16 +2094,44 @@ type: 'DO_NOTHING' }; } + +/** + * Returns an action object used in signalling that the theme global styles CPT post revisions have been received. + * Ignored from documentation as it's internal to the data store. + * + * @deprecated since WordPress 6.5.0. Callers should use `dispatch( 'core' ).receiveRevision` instead. + * + * @ignore + * + * @param {number} currentId The post id. + * @param {Array} revisions The global styles revisions. + * + * @return {Object} Action object. + */ +function receiveThemeGlobalStyleRevisions(currentId, revisions) { + external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeGlobalStyleRevisions()", { + since: '6.5.0', + alternative: "wp.data.dispatch( 'core' ).receiveRevisions" + }); + return { + type: 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS', + currentId, + revisions + }; +} + /** * Returns an action object used in signalling that the preview data for * a given URl has been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} url URL to preview the embed for. * @param {*} preview Preview data. * * @return {Object} Action object. */ - function receiveEmbedPreview(url, preview) { return { type: 'RECEIVE_EMBED_PREVIEW', @@ -1452,6 +2139,7 @@ preview }; } + /** * Action triggered to delete an entity record. * @@ -1467,200 +2155,176 @@ * @param {boolean} [options.throwOnError=false] If false, this action suppresses all * the exceptions. Defaults to false. */ - -const deleteEntityRecord = function (kind, name, recordId, query) { - let { - __unstableFetch = (external_wp_apiFetch_default()), - throwOnError = false - } = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; - return async _ref => { - let { - dispatch - } = _ref; - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { +const deleteEntityRecord = (kind, name, recordId, query, { + __unstableFetch = (external_wp_apiFetch_default()), + throwOnError = false +} = {}) => async ({ + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + let error; + let deletedRecord = false; + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId], { + exclusive: true + }); + try { + dispatch({ + type: 'DELETE_ENTITY_RECORD_START', kind, - name + name, + recordId }); - let error; - let deletedRecord = false; - - if (!entityConfig || entityConfig !== null && entityConfig !== void 0 && entityConfig.__experimentalNoFetch) { - return; - } - - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId], { - exclusive: true - }); - + let hasError = false; try { - dispatch({ - type: 'DELETE_ENTITY_RECORD_START', - kind, - name, - recordId + let path = `${entityConfig.baseURL}/${recordId}`; + if (query) { + path = (0,external_wp_url_namespaceObject.addQueryArgs)(path, query); + } + deletedRecord = await __unstableFetch({ + path, + method: 'DELETE' }); - let hasError = false; - - try { - let path = `${entityConfig.baseURL}/${recordId}`; - - if (query) { - path = (0,external_wp_url_namespaceObject.addQueryArgs)(path, query); - } - - deletedRecord = await __unstableFetch({ - path, - method: 'DELETE' - }); - await dispatch(removeItems(kind, name, recordId, true)); - } catch (_error) { - hasError = true; - error = _error; - } - - dispatch({ - type: 'DELETE_ENTITY_RECORD_FINISH', - kind, - name, - recordId, - error - }); - - if (hasError && throwOnError) { - throw error; - } - - return deletedRecord; - } finally { - dispatch.__unstableReleaseStoreLock(lock); + await dispatch(removeItems(kind, name, recordId, true)); + } catch (_error) { + hasError = true; + error = _error; } - }; + dispatch({ + type: 'DELETE_ENTITY_RECORD_FINISH', + kind, + name, + recordId, + error + }); + if (hasError && throwOnError) { + throw error; + } + return deletedRecord; + } finally { + dispatch.__unstableReleaseStoreLock(lock); + } }; + /** * Returns an action object that triggers an * edit to an entity record. * - * @param {string} kind Kind of the edited entity record. - * @param {string} name Name of the edited entity record. - * @param {number} recordId Record ID of the edited entity record. - * @param {Object} edits The edits. - * @param {Object} options Options for the edit. - * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. + * @param {string} kind Kind of the edited entity record. + * @param {string} name Name of the edited entity record. + * @param {number|string} recordId Record ID of the edited entity record. + * @param {Object} edits The edits. + * @param {Object} options Options for the edit. + * @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not. * * @return {Object} Action object. */ - -const editEntityRecord = function (kind, name, recordId, edits) { - let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; - return _ref2 => { - let { - select, - dispatch - } = _ref2; - const entityConfig = select.getEntityConfig(kind, name); - - if (!entityConfig) { - throw new Error(`The entity being edited (${kind}, ${name}) does not have a loaded config.`); +const editEntityRecord = (kind, name, recordId, edits, options = {}) => ({ + select, + dispatch +}) => { + const entityConfig = select.getEntityConfig(kind, name); + if (!entityConfig) { + throw new Error(`The entity being edited (${kind}, ${name}) does not have a loaded config.`); + } + const { + mergedEdits = {} + } = entityConfig; + const record = select.getRawEntityRecord(kind, name, recordId); + const editedRecord = select.getEditedEntityRecord(kind, name, recordId); + const edit = { + kind, + name, + recordId, + // Clear edits when they are equal to their persisted counterparts + // so that the property is not considered dirty. + edits: Object.keys(edits).reduce((acc, key) => { + const recordValue = record[key]; + const editedRecordValue = editedRecord[key]; + const value = mergedEdits[key] ? { + ...editedRecordValue, + ...edits[key] + } : edits[key]; + acc[key] = es6_default()(recordValue, value) ? undefined : value; + return acc; + }, {}) + }; + if (window.__experimentalEnableSync && entityConfig.syncConfig) { + if (false) {} + } else { + if (!options.undoIgnore) { + select.getUndoManager().addRecord([{ + id: { + kind, + name, + recordId + }, + changes: Object.keys(edits).reduce((acc, key) => { + acc[key] = { + from: editedRecord[key], + to: edits[key] + }; + return acc; + }, {}) + }], options.isCached); } - - const { - transientEdits = {}, - mergedEdits = {} - } = entityConfig; - const record = select.getRawEntityRecord(kind, name, recordId); - const editedRecord = select.getEditedEntityRecord(kind, name, recordId); - const edit = { - kind, - name, - recordId, - // Clear edits when they are equal to their persisted counterparts - // so that the property is not considered dirty. - edits: Object.keys(edits).reduce((acc, key) => { - const recordValue = record[key]; - const editedRecordValue = editedRecord[key]; - const value = mergedEdits[key] ? { ...editedRecordValue, - ...edits[key] - } : edits[key]; - acc[key] = (0,external_lodash_namespaceObject.isEqual)(recordValue, value) ? undefined : value; - return acc; - }, {}), - transientEdits - }; dispatch({ type: 'EDIT_ENTITY_RECORD', - ...edit, - meta: { - undo: !options.undoIgnore && { ...edit, - // Send the current values for things like the first undo stack entry. - edits: Object.keys(edits).reduce((acc, key) => { - acc[key] = editedRecord[key]; - return acc; - }, {}) - } - } + ...edit }); - }; + } }; + /** * Action triggered to undo the last edit to * an entity record, if any. */ - -const undo = () => _ref3 => { - let { - select, - dispatch - } = _ref3; - const undoEdit = select.getUndoEdit(); - - if (!undoEdit) { +const undo = () => ({ + select, + dispatch +}) => { + const undoRecord = select.getUndoManager().undo(); + if (!undoRecord) { return; } - dispatch({ - type: 'EDIT_ENTITY_RECORD', - ...undoEdit, - meta: { - isUndo: true - } + type: 'UNDO', + record: undoRecord }); }; + /** * Action triggered to redo the last undoed * edit to an entity record, if any. */ - -const redo = () => _ref4 => { - let { - select, - dispatch - } = _ref4; - const redoEdit = select.getRedoEdit(); - - if (!redoEdit) { +const redo = () => ({ + select, + dispatch +}) => { + const redoRecord = select.getUndoManager().redo(); + if (!redoRecord) { return; } - dispatch({ - type: 'EDIT_ENTITY_RECORD', - ...redoEdit, - meta: { - isRedo: true - } + type: 'REDO', + record: redoRecord }); }; + /** * Forces the creation of a new undo level. * * @return {Object} Action object. */ - -function __unstableCreateUndoLevel() { - return { - type: 'CREATE_UNDO_LEVEL' - }; -} +const __unstableCreateUndoLevel = () => ({ + select +}) => { + select.getUndoManager().addRecord(); +}; + /** * Action triggered to save an entity record. * @@ -1675,162 +2339,150 @@ * @param {boolean} [options.throwOnError=false] If false, this action suppresses all * the exceptions. Defaults to false. */ - -const saveEntityRecord = function (kind, name, record) { - let { - isAutosave = false, - __unstableFetch = (external_wp_apiFetch_default()), - throwOnError = false - } = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; - return async _ref5 => { - let { - select, - resolveSelect, - dispatch - } = _ref5; - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { +const saveEntityRecord = (kind, name, record, { + isAutosave = false, + __unstableFetch = (external_wp_apiFetch_default()), + throwOnError = false +} = {}) => async ({ + select, + resolveSelect, + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; + const recordId = record[entityIdKey]; + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId || esm_browser_v4()], { + exclusive: true + }); + try { + // Evaluate optimized edits. + // (Function edits that should be evaluated on save to avoid expensive computations on every edit.) + for (const [key, value] of Object.entries(record)) { + if (typeof value === 'function') { + const evaluatedValue = value(select.getEditedEntityRecord(kind, name, recordId)); + dispatch.editEntityRecord(kind, name, recordId, { + [key]: evaluatedValue + }, { + undoIgnore: true + }); + record[key] = evaluatedValue; + } + } + dispatch({ + type: 'SAVE_ENTITY_RECORD_START', kind, - name + name, + recordId, + isAutosave }); - - if (!entityConfig || entityConfig !== null && entityConfig !== void 0 && entityConfig.__experimentalNoFetch) { - return; - } - - const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; - const recordId = record[entityIdKey]; - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId || esm_browser_v4()], { - exclusive: true - }); - + let updatedRecord; + let error; + let hasError = false; try { - // Evaluate optimized edits. - // (Function edits that should be evaluated on save to avoid expensive computations on every edit.) - for (const [key, value] of Object.entries(record)) { - if (typeof value === 'function') { - const evaluatedValue = value(select.getEditedEntityRecord(kind, name, recordId)); - dispatch.editEntityRecord(kind, name, recordId, { - [key]: evaluatedValue - }, { - undoIgnore: true - }); - record[key] = evaluatedValue; - } - } - - dispatch({ - type: 'SAVE_ENTITY_RECORD_START', - kind, - name, - recordId, - isAutosave - }); - let updatedRecord; - let error; - let hasError = false; - - try { - const path = `${entityConfig.baseURL}${recordId ? '/' + recordId : ''}`; - const persistedRecord = select.getRawEntityRecord(kind, name, recordId); - - if (isAutosave) { - // Most of this autosave logic is very specific to posts. - // This is fine for now as it is the only supported autosave, - // but ideally this should all be handled in the back end, - // so the client just sends and receives objects. - const currentUser = select.getCurrentUser(); - const currentUserId = currentUser ? currentUser.id : undefined; - const autosavePost = await resolveSelect.getAutosave(persistedRecord.type, persistedRecord.id, currentUserId); // Autosaves need all expected fields to be present. - // So we fallback to the previous autosave and then - // to the actual persisted entity if the edits don't - // have a value. - - let data = { ...persistedRecord, - ...autosavePost, - ...record + const path = `${entityConfig.baseURL}${recordId ? '/' + recordId : ''}`; + const persistedRecord = select.getRawEntityRecord(kind, name, recordId); + if (isAutosave) { + // Most of this autosave logic is very specific to posts. + // This is fine for now as it is the only supported autosave, + // but ideally this should all be handled in the back end, + // so the client just sends and receives objects. + const currentUser = select.getCurrentUser(); + const currentUserId = currentUser ? currentUser.id : undefined; + const autosavePost = await resolveSelect.getAutosave(persistedRecord.type, persistedRecord.id, currentUserId); + // Autosaves need all expected fields to be present. + // So we fallback to the previous autosave and then + // to the actual persisted entity if the edits don't + // have a value. + let data = { + ...persistedRecord, + ...autosavePost, + ...record + }; + data = Object.keys(data).reduce((acc, key) => { + if (['title', 'excerpt', 'content', 'meta'].includes(key)) { + acc[key] = data[key]; + } + return acc; + }, { + // Do not update the `status` if we have edited it when auto saving. + // It's very important to let the user explicitly save this change, + // because it can lead to unexpected results. An example would be to + // have a draft post and change the status to publish. + status: data.status === 'auto-draft' ? 'draft' : undefined + }); + updatedRecord = await __unstableFetch({ + path: `${path}/autosaves`, + method: 'POST', + data + }); + + // An autosave may be processed by the server as a regular save + // when its update is requested by the author and the post had + // draft or auto-draft status. + if (persistedRecord.id === updatedRecord.id) { + let newRecord = { + ...persistedRecord, + ...data, + ...updatedRecord }; - data = Object.keys(data).reduce((acc, key) => { + newRecord = Object.keys(newRecord).reduce((acc, key) => { + // These properties are persisted in autosaves. if (['title', 'excerpt', 'content'].includes(key)) { - acc[key] = data[key]; + acc[key] = newRecord[key]; + } else if (key === 'status') { + // Status is only persisted in autosaves when going from + // "auto-draft" to "draft". + acc[key] = persistedRecord.status === 'auto-draft' && newRecord.status === 'draft' ? newRecord.status : persistedRecord.status; + } else { + // These properties are not persisted in autosaves. + acc[key] = persistedRecord[key]; } - return acc; - }, { - status: data.status === 'auto-draft' ? 'draft' : data.status - }); - updatedRecord = await __unstableFetch({ - path: `${path}/autosaves`, - method: 'POST', - data - }); // An autosave may be processed by the server as a regular save - // when its update is requested by the author and the post had - // draft or auto-draft status. - - if (persistedRecord.id === updatedRecord.id) { - let newRecord = { ...persistedRecord, - ...data, - ...updatedRecord - }; - newRecord = Object.keys(newRecord).reduce((acc, key) => { - // These properties are persisted in autosaves. - if (['title', 'excerpt', 'content'].includes(key)) { - acc[key] = newRecord[key]; - } else if (key === 'status') { - // Status is only persisted in autosaves when going from - // "auto-draft" to "draft". - acc[key] = persistedRecord.status === 'auto-draft' && newRecord.status === 'draft' ? newRecord.status : persistedRecord.status; - } else { - // These properties are not persisted in autosaves. - acc[key] = persistedRecord[key]; - } - - return acc; - }, {}); - dispatch.receiveEntityRecords(kind, name, newRecord, undefined, true); - } else { - dispatch.receiveAutosaves(persistedRecord.id, updatedRecord); - } + }, {}); + dispatch.receiveEntityRecords(kind, name, newRecord, undefined, true); } else { - let edits = record; - - if (entityConfig.__unstablePrePersist) { - edits = { ...edits, - ...entityConfig.__unstablePrePersist(persistedRecord, edits) - }; - } - - updatedRecord = await __unstableFetch({ - path, - method: recordId ? 'PUT' : 'POST', - data: edits - }); - dispatch.receiveEntityRecords(kind, name, updatedRecord, undefined, true, edits); + dispatch.receiveAutosaves(persistedRecord.id, updatedRecord); } - } catch (_error) { - hasError = true; - error = _error; + } else { + let edits = record; + if (entityConfig.__unstablePrePersist) { + edits = { + ...edits, + ...entityConfig.__unstablePrePersist(persistedRecord, edits) + }; + } + updatedRecord = await __unstableFetch({ + path, + method: recordId ? 'PUT' : 'POST', + data: edits + }); + dispatch.receiveEntityRecords(kind, name, updatedRecord, undefined, true, edits); } - - dispatch({ - type: 'SAVE_ENTITY_RECORD_FINISH', - kind, - name, - recordId, - error, - isAutosave - }); - - if (hasError && throwOnError) { - throw error; - } - - return updatedRecord; - } finally { - dispatch.__unstableReleaseStoreLock(lock); + } catch (_error) { + hasError = true; + error = _error; } - }; + dispatch({ + type: 'SAVE_ENTITY_RECORD_FINISH', + kind, + name, + recordId, + error, + isAutosave + }); + if (hasError && throwOnError) { + throw error; + } + return updatedRecord; + } finally { + dispatch.__unstableReleaseStoreLock(lock); + } }; + /** * Runs multiple core-data actions at the same time using one API request. * @@ -1853,36 +2505,35 @@ * @return {(thunkArgs: Object) => Promise} A promise that resolves to an array containing the return * values of each function given in `requests`. */ - -const __experimentalBatch = requests => async _ref6 => { - let { - dispatch - } = _ref6; +const __experimentalBatch = requests => async ({ + dispatch +}) => { const batch = createBatch(); const api = { saveEntityRecord(kind, name, record, options) { - return batch.add(add => dispatch.saveEntityRecord(kind, name, record, { ...options, + return batch.add(add => dispatch.saveEntityRecord(kind, name, record, { + ...options, __unstableFetch: add })); }, - saveEditedEntityRecord(kind, name, recordId, options) { - return batch.add(add => dispatch.saveEditedEntityRecord(kind, name, recordId, { ...options, + return batch.add(add => dispatch.saveEditedEntityRecord(kind, name, recordId, { + ...options, __unstableFetch: add })); }, - deleteEntityRecord(kind, name, recordId, query, options) { - return batch.add(add => dispatch.deleteEntityRecord(kind, name, recordId, query, { ...options, + return batch.add(add => dispatch.deleteEntityRecord(kind, name, recordId, query, { + ...options, __unstableFetch: add })); } - }; const resultPromises = requests.map(request => request(api)); const [, ...results] = await Promise.all([batch.run(), ...resultPromises]); return results; }; + /** * Action triggered to save an entity record's edits. * @@ -1891,27 +2542,18 @@ * @param {Object} recordId ID of the record. * @param {Object} options Saving options. */ - -const saveEditedEntityRecord = (kind, name, recordId, options) => async _ref7 => { - let { - select, - dispatch - } = _ref7; - +const saveEditedEntityRecord = (kind, name, recordId, options) => async ({ + select, + dispatch +}) => { if (!select.hasEditsForEntityRecord(kind, name, recordId)) { return; } - - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { - kind, - name - }); - + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); if (!entityConfig) { return; } - const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY; const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); const record = { @@ -1920,37 +2562,42 @@ }; return await dispatch.saveEntityRecord(kind, name, record, options); }; + /** * Action triggered to save only specified properties for the entity. * * @param {string} kind Kind of the entity. * @param {string} name Name of the entity. * @param {Object} recordId ID of the record. - * @param {Array} itemsToSave List of entity properties to save. + * @param {Array} itemsToSave List of entity properties or property paths to save. * @param {Object} options Saving options. */ - -const __experimentalSaveSpecifiedEntityEdits = (kind, name, recordId, itemsToSave, options) => async _ref8 => { - let { - select, - dispatch - } = _ref8; - +const __experimentalSaveSpecifiedEntityEdits = (kind, name, recordId, itemsToSave, options) => async ({ + select, + dispatch +}) => { if (!select.hasEditsForEntityRecord(kind, name, recordId)) { return; } - const edits = select.getEntityRecordNonTransientEdits(kind, name, recordId); const editsToSave = {}; - - for (const edit in edits) { - if (itemsToSave.some(item => item === edit)) { - editsToSave[edit] = edits[edit]; - } - } - + for (const item of itemsToSave) { + setNestedValue(editsToSave, item, getNestedValue(edits, item)); + } + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + const entityIdKey = entityConfig?.key || DEFAULT_ENTITY_KEY; + + // If a record key is provided then update the existing record. + // This necessitates providing `recordKey` to saveEntityRecord as part of the + // `record` argument (here called `editsToSave`) to stop that action creating + // a new record and instead cause it to update the existing record. + if (recordId) { + editsToSave[entityIdKey] = recordId; + } return await dispatch.saveEntityRecord(kind, name, editsToSave, options); }; + /** * Returns an action object used in signalling that Upload permissions have been received. * @@ -1960,7 +2607,6 @@ * * @return {Object} Action object. */ - function receiveUploadPermissions(hasUploadPermissions) { external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveUploadPermissions", { since: '5.9', @@ -1968,16 +2614,19 @@ }); return receiveUserPermission('create/media', hasUploadPermissions); } + /** * Returns an action object used in signalling that the current user has * permission to perform an action on a REST resource. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {string} key A key that represents the action and REST resource. * @param {boolean} isAllowed Whether or not the user can perform the action. * * @return {Object} Action object. */ - function receiveUserPermission(key, isAllowed) { return { type: 'RECEIVE_USER_PERMISSION', @@ -1985,35 +2634,100 @@ isAllowed }; } + /** * Returns an action object used in signalling that the autosaves for a * post have been received. + * Ignored from documentation as it's internal to the data store. + * + * @ignore * * @param {number} postId The id of the post that is parent to the autosave. * @param {Array|Object} autosaves An array of autosaves or singular autosave object. * * @return {Object} Action object. */ - function receiveAutosaves(postId, autosaves) { return { type: 'RECEIVE_AUTOSAVES', postId, - autosaves: (0,external_lodash_namespaceObject.castArray)(autosaves) + autosaves: Array.isArray(autosaves) ? autosaves : [autosaves] + }; +} + +/** + * Returns an action object signalling that the fallback Navigation + * Menu id has been received. + * + * @param {integer} fallbackId the id of the fallback Navigation Menu + * @return {Object} Action object. + */ +function receiveNavigationFallbackId(fallbackId) { + return { + type: 'RECEIVE_NAVIGATION_FALLBACK_ID', + fallbackId + }; +} + +/** + * Returns an action object used to set the template for a given query. + * + * @param {Object} query The lookup query. + * @param {string} templateId The resolved template id. + * + * @return {Object} Action object. + */ +function receiveDefaultTemplateId(query, templateId) { + return { + type: 'RECEIVE_DEFAULT_TEMPLATE', + query, + templateId }; } +/** + * Action triggered to receive revision items. + * + * @param {string} kind Kind of the received entity record revisions. + * @param {string} name Name of the received entity record revisions. + * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch. + * @param {Array|Object} records Revisions received. + * @param {?Object} query Query Object. + * @param {?boolean} invalidateCache Should invalidate query caches. + * @param {?Object} meta Meta information about pagination. + */ +const receiveRevisions = (kind, name, recordKey, records, query, invalidateCache = false, meta) => async ({ + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.kind === kind && config.name === name); + const key = entityConfig && entityConfig?.revisionKey ? entityConfig.revisionKey : DEFAULT_ENTITY_KEY; + dispatch({ + type: 'RECEIVE_ITEM_REVISIONS', + key, + items: Array.isArray(records) ? records : [records], + recordKey, + meta, + query, + kind, + name, + invalidateCache + }); +}; + ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/entities.js /** * External dependencies */ + /** * WordPress dependencies */ + /** * Internal dependencies */ @@ -2023,20 +2737,35 @@ const POST_RAW_ATTRIBUTES = ['title', 'excerpt', 'content']; const rootEntitiesConfig = [{ label: (0,external_wp_i18n_namespaceObject.__)('Base'), + kind: 'root', name: '__unstableBase', - kind: 'root', baseURL: '/', baseURLParams: { _fields: ['description', 'gmt_offset', 'home', 'name', 'site_icon', 'site_icon_url', 'site_logo', 'timezone_string', 'url'].join(',') - } -}, { - label: (0,external_wp_i18n_namespaceObject.__)('Site'), - name: 'site', - kind: 'root', - baseURL: '/wp/v2/settings', - getTitle: record => { - return (0,external_lodash_namespaceObject.get)(record, ['title'], (0,external_wp_i18n_namespaceObject.__)('Site Title')); - } + }, + // The entity doesn't support selecting multiple records. + // The property is maintained for backward compatibility. + plural: '__unstableBases', + syncConfig: { + fetch: async () => { + return external_wp_apiFetch_default()({ + path: '/' + }); + }, + applyChangesToDoc: (doc, changes) => { + const document = doc.getMap('document'); + Object.entries(changes).forEach(([key, value]) => { + if (document.get(key) !== value) { + document.set(key, value); + } + }); + }, + fromCRDTDoc: doc => { + return doc.getMap('document').toJSON(); + } + }, + syncObjectType: 'root/base', + getSyncObjectId: () => 'index' }, { label: (0,external_wp_i18n_namespaceObject.__)('Post Type'), name: 'postType', @@ -2046,7 +2775,27 @@ baseURLParams: { context: 'edit' }, - rawAttributes: POST_RAW_ATTRIBUTES + plural: 'postTypes', + syncConfig: { + fetch: async id => { + return external_wp_apiFetch_default()({ + path: `/wp/v2/types/${id}?context=edit` + }); + }, + applyChangesToDoc: (doc, changes) => { + const document = doc.getMap('document'); + Object.entries(changes).forEach(([key, value]) => { + if (document.get(key) !== value) { + document.set(key, value); + } + }); + }, + fromCRDTDoc: doc => { + return doc.getMap('document').toJSON(); + } + }, + syncObjectType: 'root/postType', + getSyncObjectId: id => id }, { name: 'media', kind: 'root', @@ -2056,7 +2805,8 @@ }, plural: 'mediaItems', label: (0,external_wp_i18n_namespaceObject.__)('Media'), - rawAttributes: ['caption', 'title', 'description'] + rawAttributes: ['caption', 'title', 'description'], + supportsPagination: true }, { name: 'taxonomy', kind: 'root', @@ -2071,6 +2821,9 @@ name: 'sidebar', kind: 'root', baseURL: '/wp/v2/sidebars', + baseURLParams: { + context: 'edit' + }, plural: 'sidebars', transientEdits: { blocks: true @@ -2133,7 +2886,7 @@ }, plural: 'menuItems', label: (0,external_wp_i18n_namespaceObject.__)('Menu Item'), - rawAttributes: ['title', 'content'] + rawAttributes: ['title'] }, { name: 'menuLocation', kind: 'root', @@ -2153,12 +2906,10 @@ context: 'edit' }, plural: 'globalStylesVariations', - // Should be different than name. - getTitle: record => { - var _record$title; - - return (record === null || record === void 0 ? void 0 : (_record$title = record.title) === null || _record$title === void 0 ? void 0 : _record$title.rendered) || (record === null || record === void 0 ? void 0 : record.title); - } + // Should be different from name. + getTitle: record => record?.title?.rendered || record?.title, + getRevisionsUrl: (parentId, revisionId) => `/wp/v2/global-styles/${parentId}/revisions${revisionId ? '/' + revisionId : ''}`, + supportsPagination: true }, { label: (0,external_wp_i18n_namespaceObject.__)('Themes'), name: 'theme', @@ -2167,6 +2918,7 @@ baseURLParams: { context: 'edit' }, + plural: 'themes', key: 'stylesheet' }, { label: (0,external_wp_i18n_namespaceObject.__)('Plugins'), @@ -2176,7 +2928,18 @@ baseURLParams: { context: 'edit' }, + plural: 'plugins', key: 'plugin' +}, { + label: (0,external_wp_i18n_namespaceObject.__)('Status'), + name: 'status', + kind: 'root', + baseURL: '/wp/v2/statuses', + baseURLParams: { + context: 'edit' + }, + plural: 'statuses', + key: 'slug' }]; const additionalEntityConfigLoaders = [{ kind: 'postType', @@ -2184,7 +2947,13 @@ }, { kind: 'taxonomy', loadEntities: loadTaxonomyEntities +}, { + kind: 'root', + name: 'site', + plural: 'sites', + loadEntities: loadSiteEntity }]; + /** * Returns a function to be used to retrieve extra edits to apply before persisting a post type. * @@ -2192,39 +2961,61 @@ * @param {Object} edits Edits. * @return {Object} Updated edits. */ - const prePersistPostType = (persistedRecord, edits) => { const newEdits = {}; - - if ((persistedRecord === null || persistedRecord === void 0 ? void 0 : persistedRecord.status) === 'auto-draft') { + if (persistedRecord?.status === 'auto-draft') { // Saving an auto-draft should create a draft by default. if (!edits.status && !newEdits.status) { newEdits.status = 'draft'; - } // Fix the auto-draft default title. - - - if ((!edits.title || edits.title === 'Auto Draft') && !newEdits.title && (!(persistedRecord !== null && persistedRecord !== void 0 && persistedRecord.title) || (persistedRecord === null || persistedRecord === void 0 ? void 0 : persistedRecord.title) === 'Auto Draft')) { + } + + // Fix the auto-draft default title. + if ((!edits.title || edits.title === 'Auto Draft') && !newEdits.title && (!persistedRecord?.title || persistedRecord?.title === 'Auto Draft')) { newEdits.title = ''; } } - return newEdits; }; +const serialisableBlocksCache = new WeakMap(); +function makeBlockAttributesSerializable(attributes) { + const newAttributes = { + ...attributes + }; + for (const [key, value] of Object.entries(attributes)) { + if (value instanceof external_wp_richText_namespaceObject.RichTextData) { + newAttributes[key] = value.valueOf(); + } + } + return newAttributes; +} +function makeBlocksSerializable(blocks) { + return blocks.map(block => { + const { + innerBlocks, + attributes, + ...rest + } = block; + return { + ...rest, + attributes: makeBlockAttributesSerializable(attributes), + innerBlocks: makeBlocksSerializable(innerBlocks) + }; + }); +} + /** * Returns the list of post type entities. * * @return {Promise} Entities promise */ - async function loadPostTypeEntities() { const postTypes = await external_wp_apiFetch_default()({ path: '/wp/v2/types?context=view' }); - return (0,external_lodash_namespaceObject.map)(postTypes, (postType, name) => { + return Object.entries(postTypes !== null && postTypes !== void 0 ? postTypes : {}).map(([name, postType]) => { var _postType$rest_namesp; - const isTemplate = ['wp_template', 'wp_template_part'].includes(name); - const namespace = (_postType$rest_namesp = postType === null || postType === void 0 ? void 0 : postType.rest_namespace) !== null && _postType$rest_namesp !== void 0 ? _postType$rest_namesp : 'wp/v2'; + const namespace = (_postType$rest_namesp = postType?.rest_namespace) !== null && _postType$rest_namesp !== void 0 ? _postType$rest_namesp : 'wp/v2'; return { kind: 'postType', baseURL: `/${namespace}/${postType.rest_base}`, @@ -2242,30 +3033,58 @@ }, rawAttributes: POST_RAW_ATTRIBUTES, getTitle: record => { - var _record$title2; - - return (record === null || record === void 0 ? void 0 : (_record$title2 = record.title) === null || _record$title2 === void 0 ? void 0 : _record$title2.rendered) || (record === null || record === void 0 ? void 0 : record.title) || (isTemplate ? (0,external_lodash_namespaceObject.startCase)(record.slug) : String(record.id)); + var _record$slug; + return record?.title?.rendered || record?.title || (isTemplate ? capitalCase((_record$slug = record.slug) !== null && _record$slug !== void 0 ? _record$slug : '') : String(record.id)); }, __unstablePrePersist: isTemplate ? undefined : prePersistPostType, - __unstable_rest_base: postType.rest_base + __unstable_rest_base: postType.rest_base, + syncConfig: { + fetch: async id => { + return external_wp_apiFetch_default()({ + path: `/${namespace}/${postType.rest_base}/${id}?context=edit` + }); + }, + applyChangesToDoc: (doc, changes) => { + const document = doc.getMap('document'); + Object.entries(changes).forEach(([key, value]) => { + if (typeof value !== 'function') { + if (key === 'blocks') { + if (!serialisableBlocksCache.has(value)) { + serialisableBlocksCache.set(value, makeBlocksSerializable(value)); + } + value = serialisableBlocksCache.get(value); + } + if (document.get(key) !== value) { + document.set(key, value); + } + } + }); + }, + fromCRDTDoc: doc => { + return doc.getMap('document').toJSON(); + } + }, + syncObjectType: 'postType/' + postType.name, + getSyncObjectId: id => id, + supportsPagination: true, + getRevisionsUrl: (parentId, revisionId) => `/${namespace}/${postType.rest_base}/${parentId}/revisions${revisionId ? '/' + revisionId : ''}`, + revisionKey: isTemplate ? 'wp_id' : DEFAULT_ENTITY_KEY }; }); } + /** * Returns the list of the taxonomies entities. * * @return {Promise} Entities promise */ - - async function loadTaxonomyEntities() { const taxonomies = await external_wp_apiFetch_default()({ path: '/wp/v2/taxonomies?context=view' }); - return (0,external_lodash_namespaceObject.map)(taxonomies, (taxonomy, name) => { + return Object.entries(taxonomies !== null && taxonomies !== void 0 ? taxonomies : {}).map(([name, taxonomy]) => { var _taxonomy$rest_namesp; - - const namespace = (_taxonomy$rest_namesp = taxonomy === null || taxonomy === void 0 ? void 0 : taxonomy.rest_namespace) !== null && _taxonomy$rest_namesp !== void 0 ? _taxonomy$rest_namesp : 'wp/v2'; + const namespace = (_taxonomy$rest_namesp = taxonomy?.rest_namespace) !== null && _taxonomy$rest_namesp !== void 0 ? _taxonomy$rest_namesp : 'wp/v2'; return { kind: 'taxonomy', baseURL: `/${namespace}/${taxonomy.rest_base}`, @@ -2277,67 +3096,131 @@ }; }); } -/** - * Returns the entity's getter method name given its kind and name. + +/** + * Returns the Site entity. + * + * @return {Promise} Entity promise + */ +async function loadSiteEntity() { + var _site$schema$properti; + const entity = { + label: (0,external_wp_i18n_namespaceObject.__)('Site'), + name: 'site', + kind: 'root', + baseURL: '/wp/v2/settings', + syncConfig: { + fetch: async () => { + return external_wp_apiFetch_default()({ + path: '/wp/v2/settings' + }); + }, + applyChangesToDoc: (doc, changes) => { + const document = doc.getMap('document'); + Object.entries(changes).forEach(([key, value]) => { + if (document.get(key) !== value) { + document.set(key, value); + } + }); + }, + fromCRDTDoc: doc => { + return doc.getMap('document').toJSON(); + } + }, + syncObjectType: 'root/site', + getSyncObjectId: () => 'index', + meta: {} + }; + const site = await external_wp_apiFetch_default()({ + path: entity.baseURL, + method: 'OPTIONS' + }); + const labels = {}; + Object.entries((_site$schema$properti = site?.schema?.properties) !== null && _site$schema$properti !== void 0 ? _site$schema$properti : {}).forEach(([key, value]) => { + // Ignore properties `title` and `type` keys. + if (typeof value === 'object' && value.title) { + labels[key] = value.title; + } + }); + return [{ + ...entity, + meta: { + labels + } + }]; +} + +/** + * Returns the entity's getter method name given its kind and name or plural name. * * @example * ```js * const nameSingular = getMethodName( 'root', 'theme', 'get' ); * // nameSingular is getRootTheme * - * const namePlural = getMethodName( 'root', 'theme', 'set' ); + * const namePlural = getMethodName( 'root', 'themes', 'set' ); * // namePlural is setRootThemes * ``` * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {string} prefix Function prefix. - * @param {boolean} usePlural Whether to use the plural form or not. + * @param {string} kind Entity kind. + * @param {string} name Entity name or plural name. + * @param {string} prefix Function prefix. * * @return {string} Method name */ - - -const getMethodName = function (kind, name) { - let prefix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'get'; - let usePlural = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - const entityConfig = (0,external_lodash_namespaceObject.find)(rootEntitiesConfig, { - kind, - name - }); - const kindPrefix = kind === 'root' ? '' : (0,external_lodash_namespaceObject.upperFirst)((0,external_lodash_namespaceObject.camelCase)(kind)); - const nameSuffix = (0,external_lodash_namespaceObject.upperFirst)((0,external_lodash_namespaceObject.camelCase)(name)) + (usePlural ? 's' : ''); - const suffix = usePlural && entityConfig !== null && entityConfig !== void 0 && entityConfig.plural ? (0,external_lodash_namespaceObject.upperFirst)((0,external_lodash_namespaceObject.camelCase)(entityConfig.plural)) : nameSuffix; +const getMethodName = (kind, name, prefix = 'get') => { + const kindPrefix = kind === 'root' ? '' : pascalCase(kind); + const suffix = pascalCase(name); return `${prefix}${kindPrefix}${suffix}`; }; -/** - * Loads the kind entities into the store. +function registerSyncConfigs(configs) { + configs.forEach(({ + syncObjectType, + syncConfig + }) => { + getSyncProvider().register(syncObjectType, syncConfig); + const editSyncConfig = { + ...syncConfig + }; + delete editSyncConfig.fetch; + getSyncProvider().register(syncObjectType + '--edit', editSyncConfig); + }); +} + +/** + * Loads the entities into the store. + * + * Note: The `name` argument is used for `root` entities requiring additional server data. * * @param {string} kind Kind - * + * @param {string} name Name * @return {(thunkArgs: object) => Promise} Entities */ - -const getOrLoadEntitiesConfig = kind => async _ref => { - let { - select, - dispatch - } = _ref; +const getOrLoadEntitiesConfig = (kind, name) => async ({ + select, + dispatch +}) => { let configs = select.getEntitiesConfig(kind); - - if (configs && configs.length !== 0) { + const hasConfig = !!select.getEntityConfig(kind, name); + if (configs?.length > 0 && hasConfig) { + if (window.__experimentalEnableSync) { + if (false) {} + } return configs; } - - const loader = (0,external_lodash_namespaceObject.find)(additionalEntityConfigLoaders, { - kind + const loader = additionalEntityConfigLoaders.find(l => { + if (!name || !l.name) { + return l.kind === kind; + } + return l.kind === kind && l.name === name; }); - if (!loader) { return []; } - configs = await loader.loadEntities(); + if (window.__experimentalEnableSync) { + if (false) {} + } dispatch(addEntities(configs)); return configs; }; @@ -2358,18 +3241,12 @@ } else if (Array.isArray(value)) { return value; } - return null; } - -/* harmony default export */ var get_normalized_comma_separable = (getNormalizedCommaSeparable); +/* harmony default export */ const get_normalized_comma_separable = (getNormalizedCommaSeparable); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/with-weak-map-cache.js /** - * External dependencies - */ - -/** * Given a function, returns an enhanced function which caches the result and * tracks in WeakMap. The result is only cached if the original function is * passed a valid object-like argument (requirement for WeakMap key). @@ -2378,35 +3255,33 @@ * * @return {Function} Enhanced caching function. */ - function withWeakMapCache(fn) { const cache = new WeakMap(); return key => { let value; - if (cache.has(key)) { value = cache.get(key); } else { - value = fn(key); // Can reach here if key is not valid for WeakMap, since `has` + value = fn(key); + + // Can reach here if key is not valid for WeakMap, since `has` // will return false for invalid key. Since `set` will throw, // ensure that key is valid before setting into cache. - - if ((0,external_lodash_namespaceObject.isObjectLike)(key)) { + if (key !== null && typeof key === 'object') { cache.set(key, value); } } - return value; }; } - -/* harmony default export */ var with_weak_map_cache = (withWeakMapCache); +/* harmony default export */ const with_weak_map_cache = (withWeakMapCache); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/get-query-parts.js /** * WordPress dependencies */ + /** * Internal dependencies */ @@ -2437,7 +3312,6 @@ * * @return {WPQueriedDataQueryParts} Query parts. */ - function getQueryParts(query) { /** * @type {WPQueriedDataQueryParts} @@ -2449,27 +3323,23 @@ fields: null, include: null, context: 'default' - }; // Ensure stable key by sorting keys. Also more efficient for iterating. - + }; + + // Ensure stable key by sorting keys. Also more efficient for iterating. const keys = Object.keys(query).sort(); - for (let i = 0; i < keys.length; i++) { const key = keys[i]; let value = query[key]; - switch (key) { case 'page': parts[key] = Number(value); break; - case 'per_page': parts.perPage = Number(value); break; - case 'context': parts.context = value; break; - default: // While in theory, we could exclude "_fields" from the stableKey // because two request with different fields have the same results @@ -2478,72 +3348,62 @@ // Example: Asking for titles in posts without title support. if (key === '_fields') { var _getNormalizedCommaSe; - - parts.fields = (_getNormalizedCommaSe = get_normalized_comma_separable(value)) !== null && _getNormalizedCommaSe !== void 0 ? _getNormalizedCommaSe : []; // Make sure to normalize value for `stableKey` - + parts.fields = (_getNormalizedCommaSe = get_normalized_comma_separable(value)) !== null && _getNormalizedCommaSe !== void 0 ? _getNormalizedCommaSe : []; + // Make sure to normalize value for `stableKey` value = parts.fields.join(); - } // Two requests with different include values cannot have same results. - - + } + + // Two requests with different include values cannot have same results. if (key === 'include') { var _getNormalizedCommaSe2; - if (typeof value === 'number') { value = value.toString(); } - - parts.include = ((_getNormalizedCommaSe2 = get_normalized_comma_separable(value)) !== null && _getNormalizedCommaSe2 !== void 0 ? _getNormalizedCommaSe2 : []).map(Number); // Normalize value for `stableKey`. - + parts.include = ((_getNormalizedCommaSe2 = get_normalized_comma_separable(value)) !== null && _getNormalizedCommaSe2 !== void 0 ? _getNormalizedCommaSe2 : []).map(Number); + // Normalize value for `stableKey`. value = parts.include.join(); - } // While it could be any deterministic string, for simplicity's + } + + // While it could be any deterministic string, for simplicity's // sake mimic querystring encoding for stable key. // // TODO: For consistency with PHP implementation, addQueryArgs // should accept a key value pair, which may optimize its // implementation for our use here, vs. iterating an object // with only a single key. - - parts.stableKey += (parts.stableKey ? '&' : '') + (0,external_wp_url_namespaceObject.addQueryArgs)('', { [key]: value }).slice(1); } } - return parts; } -/* harmony default export */ var get_query_parts = (with_weak_map_cache(getQueryParts)); +/* harmony default export */ const get_query_parts = (with_weak_map_cache(getQueryParts)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/reducer.js /** - * External dependencies - */ - -/** * WordPress dependencies */ + /** * Internal dependencies */ - - function getContextFromAction(action) { const { query } = action; - if (!query) { return 'default'; } - const queryParts = get_query_parts(query); return queryParts.context; } + /** * Returns a merged array of item IDs, given details of the received paginated * items. The array is sparse-like with `undefined` entries where holes exist. @@ -2555,32 +3415,48 @@ * * @return {number[]} Merged array of item IDs. */ - - function getMergedItemIds(itemIds, nextItemIds, page, perPage) { var _itemIds$length; - const receivedAllIds = page === 1 && perPage === -1; - if (receivedAllIds) { return nextItemIds; } - - const nextItemIdsStartIndex = (page - 1) * perPage; // If later page has already been received, default to the larger known + const nextItemIdsStartIndex = (page - 1) * perPage; + + // If later page has already been received, default to the larger known // size of the existing array, else calculate as extending the existing. - - const size = Math.max((_itemIds$length = itemIds === null || itemIds === void 0 ? void 0 : itemIds.length) !== null && _itemIds$length !== void 0 ? _itemIds$length : 0, nextItemIdsStartIndex + nextItemIds.length); // Preallocate array since size is known. - + const size = Math.max((_itemIds$length = itemIds?.length) !== null && _itemIds$length !== void 0 ? _itemIds$length : 0, nextItemIdsStartIndex + nextItemIds.length); + + // Preallocate array since size is known. const mergedItemIds = new Array(size); - for (let i = 0; i < size; i++) { // Preserve existing item ID except for subset of range of next items. - const isInNextItemsRange = i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + nextItemIds.length; - mergedItemIds[i] = isInNextItemsRange ? nextItemIds[i - nextItemIdsStartIndex] : itemIds === null || itemIds === void 0 ? void 0 : itemIds[i]; - } - + // We need to check against the possible maximum upper boundary because + // a page could receive fewer than what was previously stored. + const isInNextItemsRange = i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage; + mergedItemIds[i] = isInNextItemsRange ? nextItemIds[i - nextItemIdsStartIndex] : itemIds?.[i]; + } return mergedItemIds; } + +/** + * Helper function to filter out entities with certain IDs. + * Entities are keyed by their ID. + * + * @param {Object} entities Entity objects, keyed by entity ID. + * @param {Array} ids Entity IDs to filter out. + * + * @return {Object} Filtered entities. + */ +function removeEntitiesById(entities, ids) { + return Object.fromEntries(Object.entries(entities).filter(([id]) => !ids.some(itemId => { + if (Number.isInteger(itemId)) { + return itemId === +id; + } + return itemId === id; + }))); +} + /** * Reducer tracking items state, keyed by ID. Items are assumed to be normal, * where identifiers are common across all queries. @@ -2590,35 +3466,30 @@ * * @return {Object} Next state. */ - -function items() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function items(state = {}, action) { switch (action.type) { case 'RECEIVE_ITEMS': { const context = getContextFromAction(action); const key = action.key || DEFAULT_ENTITY_KEY; - return { ...state, - [context]: { ...state[context], + return { + ...state, + [context]: { + ...state[context], ...action.items.reduce((accumulator, value) => { - var _state$context; - - const itemId = value[key]; - accumulator[itemId] = conservativeMapItem(state === null || state === void 0 ? void 0 : (_state$context = state[context]) === null || _state$context === void 0 ? void 0 : _state$context[itemId], value); + const itemId = value?.[key]; + accumulator[itemId] = conservativeMapItem(state?.[context]?.[itemId], value); return accumulator; }, {}) } }; } - case 'REMOVE_ITEMS': - return (0,external_lodash_namespaceObject.mapValues)(state, contextState => (0,external_lodash_namespaceObject.omit)(contextState, action.itemIds)); - } - + return Object.fromEntries(Object.entries(state).map(([itemId, contextState]) => [itemId, removeEntitiesById(contextState, action.itemIds)])); + } return state; } + /** * Reducer tracking item completeness, keyed by ID. A complete item is one for * which all fields are known. This is used in supporting `_fields` queries, @@ -2631,11 +3502,7 @@ * * @return {Object>} Next state. */ - -function itemIsComplete() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function itemIsComplete(state = {}, action) { switch (action.type) { case 'RECEIVE_ITEMS': { @@ -2643,36 +3510,37 @@ const { query, key = DEFAULT_ENTITY_KEY - } = action; // An item is considered complete if it is received without an associated + } = action; + + // An item is considered complete if it is received without an associated // fields query. Ideally, this would be implemented in such a way where the // complete aggregate of all fields would satisfy completeness. Since the // fields are not consistent across all entities, this would require // introspection on the REST schema for each entity to know which fields // compose a complete item for that entity. - const queryParts = query ? get_query_parts(query) : {}; const isCompleteQuery = !query || !Array.isArray(queryParts.fields); - return { ...state, - [context]: { ...state[context], + return { + ...state, + [context]: { + ...state[context], ...action.items.reduce((result, item) => { - var _state$context2; - - const itemId = item[key]; // Defer to completeness if already assigned. Technically the + const itemId = item?.[key]; + + // Defer to completeness if already assigned. Technically the // data may be outdated if receiving items for a field subset. - - result[itemId] = (state === null || state === void 0 ? void 0 : (_state$context2 = state[context]) === null || _state$context2 === void 0 ? void 0 : _state$context2[itemId]) || isCompleteQuery; + result[itemId] = state?.[context]?.[itemId] || isCompleteQuery; return result; }, {}) } }; } - case 'REMOVE_ITEMS': - return (0,external_lodash_namespaceObject.mapValues)(state, contextState => (0,external_lodash_namespaceObject.omit)(contextState, action.itemIds)); - } - + return Object.fromEntries(Object.entries(state).map(([itemId, contextState]) => [itemId, removeEntitiesById(contextState, action.itemIds)])); + } return state; } + /** * Reducer tracking queries state, keyed by stable query key. Each reducer * query object includes `itemIds` and `requestingPageByPerPage`. @@ -2682,39 +3550,41 @@ * * @return {Object} Next state. */ - -const receiveQueries = (0,external_lodash_namespaceObject.flowRight)([// Limit to matching action type so we don't attempt to replace action on +const receiveQueries = (0,external_wp_compose_namespaceObject.compose)([ +// Limit to matching action type so we don't attempt to replace action on // an unhandled action. -if_matching_action(action => 'query' in action), // Inject query parts into action for use both in `onSubKey` and reducer. +if_matching_action(action => 'query' in action), +// Inject query parts into action for use both in `onSubKey` and reducer. replace_action(action => { // `ifMatchingAction` still passes on initialization, where state is // undefined and a query is not assigned. Avoid attempting to parse // parts. `onSubKey` will omit by lack of `stableKey`. if (action.query) { - return { ...action, + return { + ...action, ...get_query_parts(action.query) }; } - return action; -}), on_sub_key('context'), // Queries shape is shared, but keyed by query `stableKey` part. Original +}), on_sub_key('context'), +// Queries shape is shared, but keyed by query `stableKey` part. Original // reducer tracks only a single query object. -on_sub_key('stableKey')])(function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; - let action = arguments.length > 1 ? arguments[1] : undefined; +on_sub_key('stableKey')])((state = {}, action) => { const { type, page, perPage, key = DEFAULT_ENTITY_KEY } = action; - if (type !== 'RECEIVE_ITEMS') { return state; } - - return getMergedItemIds(state || [], (0,external_lodash_namespaceObject.map)(action.items, key), page, perPage); + return { + itemIds: getMergedItemIds(state?.itemIds || [], action.items.map(item => item?.[key]).filter(Boolean), page, perPage), + meta: action.meta + }; }); + /** * Reducer tracking queries state. * @@ -2723,34 +3593,24 @@ * * @return {Object} Next state. */ - -const queries = function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +const queries = (state = {}, action) => { switch (action.type) { case 'RECEIVE_ITEMS': return receiveQueries(state, action); - case 'REMOVE_ITEMS': const removedItems = action.itemIds.reduce((result, itemId) => { result[itemId] = true; return result; }, {}); - return (0,external_lodash_namespaceObject.mapValues)(state, contextQueries => { - return (0,external_lodash_namespaceObject.mapValues)(contextQueries, queryItems => { - return (0,external_lodash_namespaceObject.filter)(queryItems, queryId => { - return !removedItems[queryId]; - }); - }); - }); - + return Object.fromEntries(Object.entries(state).map(([queryGroup, contextQueries]) => [queryGroup, Object.fromEntries(Object.entries(contextQueries).map(([query, queryItems]) => [query, { + ...queryItems, + itemIds: queryItems.itemIds.filter(queryId => !removedItems[queryId]) + }]))])); default: return state; } }; - -/* harmony default export */ var reducer = ((0,external_wp_data_namespaceObject.combineReducers)({ +/* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({ items, itemIsComplete, queries @@ -2761,12 +3621,14 @@ * External dependencies */ + /** * WordPress dependencies */ + /** * Internal dependencies */ @@ -2787,20 +3649,17 @@ * * @return {Object} Updated state. */ - -function terms() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function terms(state = {}, action) { switch (action.type) { case 'RECEIVE_TERMS': - return { ...state, + return { + ...state, [action.taxonomy]: action.terms }; } - return state; } + /** * Reducer managing authors state. Keyed by id. * @@ -2809,28 +3668,30 @@ * * @return {Object} Updated state. */ - -function users() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { - byId: {}, - queries: {} - }; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function users(state = { + byId: {}, + queries: {} +}, action) { switch (action.type) { case 'RECEIVE_USER_QUERY': return { - byId: { ...state.byId, - ...(0,external_lodash_namespaceObject.keyBy)(action.users, 'id') + byId: { + ...state.byId, + // Key users by their ID. + ...action.users.reduce((newUsers, user) => ({ + ...newUsers, + [user.id]: user + }), {}) }, - queries: { ...state.queries, - [action.queryID]: (0,external_lodash_namespaceObject.map)(action.users, user => user.id) + queries: { + ...state.queries, + [action.queryID]: action.users.map(user => user.id) } }; } - return state; } + /** * Reducer managing current user state. * @@ -2839,18 +3700,14 @@ * * @return {Object} Updated state. */ - -function currentUser() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function currentUser(state = {}, action) { switch (action.type) { case 'RECEIVE_CURRENT_USER': return action.currentUser; } - return state; } + /** * Reducer managing taxonomies. * @@ -2859,18 +3716,14 @@ * * @return {Object} Updated state. */ - -function taxonomies() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function taxonomies(state = [], action) { switch (action.type) { case 'RECEIVE_TAXONOMIES': return action.taxonomies; } - return state; } + /** * Reducer managing the current theme. * @@ -2879,18 +3732,14 @@ * * @return {string|undefined} Updated state. */ - -function currentTheme() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function currentTheme(state = undefined, action) { switch (action.type) { case 'RECEIVE_CURRENT_THEME': return action.currentTheme.stylesheet; } - return state; } + /** * Reducer managing the current global styles id. * @@ -2899,18 +3748,14 @@ * * @return {string|undefined} Updated state. */ - -function currentGlobalStylesId() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function currentGlobalStylesId(state = undefined, action) { switch (action.type) { case 'RECEIVE_CURRENT_GLOBAL_STYLES_ID': return action.id; } - return state; } + /** * Reducer managing the theme base global styles. * @@ -2919,20 +3764,17 @@ * * @return {Record} Updated state. */ - -function themeBaseGlobalStyles() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function themeBaseGlobalStyles(state = {}, action) { switch (action.type) { case 'RECEIVE_THEME_GLOBAL_STYLES': - return { ...state, + return { + ...state, [action.stylesheet]: action.globalStyles }; } - return state; } + /** * Reducer managing the theme global styles variations. * @@ -2941,20 +3783,46 @@ * * @return {Record} Updated state. */ - -function themeGlobalStyleVariations() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function themeGlobalStyleVariations(state = {}, action) { switch (action.type) { case 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS': - return { ...state, + return { + ...state, [action.stylesheet]: action.variations }; } - return state; } +const withMultiEntityRecordEdits = reducer => (state, action) => { + if (action.type === 'UNDO' || action.type === 'REDO') { + const { + record + } = action; + let newState = state; + record.forEach(({ + id: { + kind, + name, + recordId + }, + changes + }) => { + newState = reducer(newState, { + type: 'EDIT_ENTITY_RECORD', + kind, + name, + recordId, + edits: Object.entries(changes).reduce((acc, [key, value]) => { + acc[key] = action.type === 'UNDO' ? value.from : value.to; + return acc; + }, {}) + }); + }); + return newState; + } + return reducer(state, action); +}; + /** * Higher Order Reducer for a given entity config. It supports: * @@ -2966,68 +3834,62 @@ * * @return {AnyFunction} Reducer. */ - function entity(entityConfig) { - return (0,external_lodash_namespaceObject.flowRight)([// Limit to matching action type so we don't attempt to replace action on + return (0,external_wp_compose_namespaceObject.compose)([withMultiEntityRecordEdits, + // Limit to matching action type so we don't attempt to replace action on // an unhandled action. - if_matching_action(action => action.name && action.kind && action.name === entityConfig.name && action.kind === entityConfig.kind), // Inject the entity config into the action. + if_matching_action(action => action.name && action.kind && action.name === entityConfig.name && action.kind === entityConfig.kind), + // Inject the entity config into the action. replace_action(action => { - return { ...action, - key: entityConfig.key || DEFAULT_ENTITY_KEY + return { + key: entityConfig.key || DEFAULT_ENTITY_KEY, + ...action }; })])((0,external_wp_data_namespaceObject.combineReducers)({ queriedData: reducer, - edits: function () { - var _action$query$context, _action$query; - - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - + edits: (state = {}, action) => { + var _action$query$context; switch (action.type) { case 'RECEIVE_ITEMS': - const context = (_action$query$context = action === null || action === void 0 ? void 0 : (_action$query = action.query) === null || _action$query === void 0 ? void 0 : _action$query.context) !== null && _action$query$context !== void 0 ? _action$query$context : 'default'; - + const context = (_action$query$context = action?.query?.context) !== null && _action$query$context !== void 0 ? _action$query$context : 'default'; if (context !== 'default') { return state; } - - const nextState = { ...state + const nextState = { + ...state }; - for (const record of action.items) { - const recordId = record[action.key]; + const recordId = record?.[action.key]; const edits = nextState[recordId]; - if (!edits) { continue; } - const nextEdits = Object.keys(edits).reduce((acc, key) => { + var _record$key$raw; // If the edited value is still different to the persisted value, // keep the edited value in edits. - if ( // Edits are the "raw" attribute values, but records may have + if ( + // Edits are the "raw" attribute values, but records may have // objects with more properties, so we use `get` here for the // comparison. - !(0,external_lodash_namespaceObject.isEqual)(edits[key], (0,external_lodash_namespaceObject.get)(record[key], 'raw', record[key])) && ( // Sometimes the server alters the sent value which means + !es6_default()(edits[key], (_record$key$raw = record[key]?.raw) !== null && _record$key$raw !== void 0 ? _record$key$raw : record[key]) && ( + // Sometimes the server alters the sent value which means // we need to also remove the edits before the api request. - !action.persistedEdits || !(0,external_lodash_namespaceObject.isEqual)(edits[key], action.persistedEdits[key]))) { + !action.persistedEdits || !es6_default()(edits[key], action.persistedEdits[key]))) { acc[key] = edits[key]; } - return acc; }, {}); - if (Object.keys(nextEdits).length) { nextState[recordId] = nextEdits; } else { delete nextState[recordId]; } } - return nextState; - case 'EDIT_ENTITY_RECORD': - const nextEdits = { ...state[action.recordId], + const nextEdits = { + ...state[action.recordId], ...action.edits }; Object.keys(nextEdits).forEach(key => { @@ -3037,21 +3899,19 @@ delete nextEdits[key]; } }); - return { ...state, + return { + ...state, [action.recordId]: nextEdits }; } - return state; }, - saving: function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - + saving: (state = {}, action) => { switch (action.type) { case 'SAVE_ENTITY_RECORD_START': case 'SAVE_ENTITY_RECORD_FINISH': - return { ...state, + return { + ...state, [action.recordId]: { pending: action.type === 'SAVE_ENTITY_RECORD_START', error: action.error, @@ -3059,28 +3919,49 @@ } }; } - return state; }, - deleting: function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - + deleting: (state = {}, action) => { switch (action.type) { case 'DELETE_ENTITY_RECORD_START': case 'DELETE_ENTITY_RECORD_FINISH': - return { ...state, + return { + ...state, [action.recordId]: { pending: action.type === 'DELETE_ENTITY_RECORD_START', error: action.error } }; } - + return state; + }, + revisions: (state = {}, action) => { + // Use the same queriedDataReducer shape for revisions. + if (action.type === 'RECEIVE_ITEM_REVISIONS') { + const recordKey = action.recordKey; + delete action.recordKey; + const newState = reducer(state[recordKey], { + ...action, + type: 'RECEIVE_ITEMS' + }); + return { + ...state, + [recordKey]: newState + }; + } + if (action.type === 'REMOVE_ITEMS') { + return Object.fromEntries(Object.entries(state).filter(([id]) => !action.itemIds.some(itemId => { + if (Number.isInteger(itemId)) { + return itemId === +id; + } + return itemId === id; + }))); + } return state; } })); } + /** * Reducer keeping track of the registered entities. * @@ -3089,19 +3970,14 @@ * * @return {Object} Updated state. */ - - -function entitiesConfig() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : rootEntitiesConfig; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function entitiesConfig(state = rootEntitiesConfig, action) { switch (action.type) { case 'ADD_ENTITIES': return [...state, ...action.entities]; } - return state; } + /** * Reducer keeping track of the registered entities config and data. * @@ -3110,183 +3986,58 @@ * * @return {Object} Updated state. */ - -const entities = function () { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - const newConfig = entitiesConfig(state.config, action); // Generates a dynamic reducer for the entities. - +const entities = (state = {}, action) => { + const newConfig = entitiesConfig(state.config, action); + + // Generates a dynamic reducer for the entities. let entitiesDataReducer = state.reducer; - if (!entitiesDataReducer || newConfig !== state.config) { - const entitiesByKind = (0,external_lodash_namespaceObject.groupBy)(newConfig, 'kind'); - entitiesDataReducer = (0,external_wp_data_namespaceObject.combineReducers)(Object.entries(entitiesByKind).reduce((memo, _ref) => { - let [kind, subEntities] = _ref; - const kindReducer = (0,external_wp_data_namespaceObject.combineReducers)(subEntities.reduce((kindMemo, entityConfig) => ({ ...kindMemo, + const entitiesByKind = newConfig.reduce((acc, record) => { + const { + kind + } = record; + if (!acc[kind]) { + acc[kind] = []; + } + acc[kind].push(record); + return acc; + }, {}); + entitiesDataReducer = (0,external_wp_data_namespaceObject.combineReducers)(Object.entries(entitiesByKind).reduce((memo, [kind, subEntities]) => { + const kindReducer = (0,external_wp_data_namespaceObject.combineReducers)(subEntities.reduce((kindMemo, entityConfig) => ({ + ...kindMemo, [entityConfig.name]: entity(entityConfig) }), {})); memo[kind] = kindReducer; return memo; }, {})); } - const newData = entitiesDataReducer(state.records, action); - if (newData === state.records && newConfig === state.config && entitiesDataReducer === state.reducer) { return state; } - return { reducer: entitiesDataReducer, records: newData, config: newConfig }; }; -/** - * @typedef {Object} UndoStateMeta - * - * @property {number} offset Where in the undo stack we are. - * @property {Object} [flattenedUndo] Flattened form of undo stack. - */ - -/** @typedef {Array & UndoStateMeta} UndoState */ - -/** - * @type {UndoState} - * - * @todo Given how we use this we might want to make a custom class for it. - */ - -const UNDO_INITIAL_STATE = Object.assign([], { - offset: 0 -}); -/** @type {Object} */ - -let lastEditAction; -/** - * Reducer keeping track of entity edit undo history. - * - * @param {UndoState} state Current state. - * @param {Object} action Dispatched action. - * - * @return {UndoState} Updated state. - */ - -function reducer_undo() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : UNDO_INITIAL_STATE; - let action = arguments.length > 1 ? arguments[1] : undefined; - + +/** + * @type {UndoManager} + */ +function undoManager(state = (0,build_module.createUndoManager)()) { + return state; +} +function editsReference(state = {}, action) { switch (action.type) { case 'EDIT_ENTITY_RECORD': - case 'CREATE_UNDO_LEVEL': - let isCreateUndoLevel = action.type === 'CREATE_UNDO_LEVEL'; - const isUndoOrRedo = !isCreateUndoLevel && (action.meta.isUndo || action.meta.isRedo); - - if (isCreateUndoLevel) { - action = lastEditAction; - } else if (!isUndoOrRedo) { - // Don't lose the last edit cache if the new one only has transient edits. - // Transient edits don't create new levels so updating the cache would make - // us skip an edit later when creating levels explicitly. - if (Object.keys(action.edits).some(key => !action.transientEdits[key])) { - lastEditAction = action; - } else { - lastEditAction = { ...action, - edits: { ...(lastEditAction && lastEditAction.edits), - ...action.edits - } - }; - } - } - /** @type {UndoState} */ - - - let nextState; - - if (isUndoOrRedo) { - // @ts-ignore we might consider using Object.assign({}, state) - nextState = [...state]; - nextState.offset = state.offset + (action.meta.isUndo ? -1 : 1); - - if (state.flattenedUndo) { - // The first undo in a sequence of undos might happen while we have - // flattened undos in state. If this is the case, we want execution - // to continue as if we were creating an explicit undo level. This - // will result in an extra undo level being appended with the flattened - // undo values. - // We also have to take into account if the `lastEditAction` had opted out - // of being tracked in undo history, like the action that persists the latest - // content right before saving. In that case we have to update the `lastEditAction` - // to avoid returning early before applying the existing flattened undos. - isCreateUndoLevel = true; - - if (!lastEditAction.meta.undo) { - lastEditAction.meta.undo = { - edits: {} - }; - } - - action = lastEditAction; - } else { - return nextState; - } - } - - if (!action.meta.undo) { - return state; - } // Transient edits don't create an undo level, but are - // reachable in the next meaningful edit to which they - // are merged. They are defined in the entity's config. - - - if (!isCreateUndoLevel && !Object.keys(action.edits).some(key => !action.transientEdits[key])) { - // @ts-ignore we might consider using Object.assign({}, state) - nextState = [...state]; - nextState.flattenedUndo = { ...state.flattenedUndo, - ...action.edits - }; - nextState.offset = state.offset; - return nextState; - } // Clear potential redos, because this only supports linear history. - - - nextState = // @ts-ignore this needs additional cleanup, probably involving code-level changes - nextState || state.slice(0, state.offset || undefined); - nextState.offset = nextState.offset || 0; - nextState.pop(); - - if (!isCreateUndoLevel) { - nextState.push({ - kind: action.meta.undo.kind, - name: action.meta.undo.name, - recordId: action.meta.undo.recordId, - edits: { ...state.flattenedUndo, - ...action.meta.undo.edits - } - }); - } // When an edit is a function it's an optimization to avoid running some expensive operation. - // We can't rely on the function references being the same so we opt out of comparing them here. - - - const comparisonUndoEdits = Object.values(action.meta.undo.edits).filter(edit => typeof edit !== 'function'); - const comparisonEdits = Object.values(action.edits).filter(edit => typeof edit !== 'function'); - - if (!external_wp_isShallowEqual_default()(comparisonUndoEdits, comparisonEdits)) { - nextState.push({ - kind: action.kind, - name: action.name, - recordId: action.recordId, - edits: isCreateUndoLevel ? { ...state.flattenedUndo, - ...action.edits - } : action.edits - }); - } - - return nextState; - } - + case 'UNDO': + case 'REDO': + return {}; + } return state; } + /** * Reducer managing embed preview data. * @@ -3295,24 +4046,21 @@ * * @return {Object} Updated state. */ - -function embedPreviews() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function embedPreviews(state = {}, action) { switch (action.type) { case 'RECEIVE_EMBED_PREVIEW': const { url, preview } = action; - return { ...state, + return { + ...state, [url]: preview }; } - return state; } + /** * State which tracks whether the user can perform an action on a REST * resource. @@ -3322,20 +4070,17 @@ * * @return {Object} Updated state. */ - -function userPermissions() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function userPermissions(state = {}, action) { switch (action.type) { case 'RECEIVE_USER_PERMISSION': - return { ...state, + return { + ...state, [action.key]: action.isAllowed }; } - return state; } + /** * Reducer returning autosaves keyed by their parent's post id. * @@ -3344,47 +4089,87 @@ * * @return {Object} Updated state. */ - -function autosaves() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function autosaves(state = {}, action) { switch (action.type) { case 'RECEIVE_AUTOSAVES': const { postId, autosaves: autosavesData } = action; - return { ...state, + return { + ...state, [postId]: autosavesData }; } - return state; } -function blockPatterns() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function blockPatterns(state = [], action) { switch (action.type) { case 'RECEIVE_BLOCK_PATTERNS': return action.patterns; } - return state; } -function blockPatternCategories() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - let action = arguments.length > 1 ? arguments[1] : undefined; - +function blockPatternCategories(state = [], action) { switch (action.type) { case 'RECEIVE_BLOCK_PATTERN_CATEGORIES': return action.categories; } - + return state; +} +function userPatternCategories(state = [], action) { + switch (action.type) { + case 'RECEIVE_USER_PATTERN_CATEGORIES': + return action.patternCategories; + } + return state; +} +function navigationFallbackId(state = null, action) { + switch (action.type) { + case 'RECEIVE_NAVIGATION_FALLBACK_ID': + return action.fallbackId; + } return state; } -/* harmony default export */ var build_module_reducer = ((0,external_wp_data_namespaceObject.combineReducers)({ + +/** + * Reducer managing the theme global styles revisions. + * + * @param {Record} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Record} Updated state. + */ +function themeGlobalStyleRevisions(state = {}, action) { + switch (action.type) { + case 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS': + return { + ...state, + [action.currentId]: action.revisions + }; + } + return state; +} + +/** + * Reducer managing the template lookup per query. + * + * @param {Record} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Record} Updated state. + */ +function defaultTemplates(state = {}, action) { + switch (action.type) { + case 'RECEIVE_DEFAULT_TEMPLATE': + return { + ...state, + [JSON.stringify(action.query)]: action.templateId + }; + } + return state; +} +/* harmony default export */ const build_module_reducer = ((0,external_wp_data_namespaceObject.combineReducers)({ terms, users, currentTheme, @@ -3392,294 +4177,23 @@ currentUser, themeGlobalStyleVariations, themeBaseGlobalStyles, + themeGlobalStyleRevisions, taxonomies, entities, - undo: reducer_undo, + editsReference, + undoManager, embedPreviews, userPermissions, autosaves, blockPatterns, - blockPatternCategories + blockPatternCategories, + userPatternCategories, + navigationFallbackId, + defaultTemplates })); -;// CONCATENATED MODULE: ./node_modules/rememo/es/rememo.js - - -var LEAF_KEY, hasWeakMap; - -/** - * Arbitrary value used as key for referencing cache object in WeakMap tree. - * - * @type {Object} - */ -LEAF_KEY = {}; - -/** - * Whether environment supports WeakMap. - * - * @type {boolean} - */ -hasWeakMap = typeof WeakMap !== 'undefined'; - -/** - * Returns the first argument as the sole entry in an array. - * - * @param {*} value Value to return. - * - * @return {Array} Value returned as entry in array. - */ -function arrayOf( value ) { - return [ value ]; -} - -/** - * Returns true if the value passed is object-like, or false otherwise. A value - * is object-like if it can support property assignment, e.g. object or array. - * - * @param {*} value Value to test. - * - * @return {boolean} Whether value is object-like. - */ -function isObjectLike( value ) { - return !! value && 'object' === typeof value; -} - -/** - * Creates and returns a new cache object. - * - * @return {Object} Cache object. - */ -function createCache() { - var cache = { - clear: function() { - cache.head = null; - }, - }; - - return cache; -} - -/** - * Returns true if entries within the two arrays are strictly equal by - * reference from a starting index. - * - * @param {Array} a First array. - * @param {Array} b Second array. - * @param {number} fromIndex Index from which to start comparison. - * - * @return {boolean} Whether arrays are shallowly equal. - */ -function isShallowEqual( a, b, fromIndex ) { - var i; - - if ( a.length !== b.length ) { - return false; - } - - for ( i = fromIndex; i < a.length; i++ ) { - if ( a[ i ] !== b[ i ] ) { - return false; - } - } - - return true; -} - -/** - * Returns a memoized selector function. The getDependants function argument is - * called before the memoized selector and is expected to return an immutable - * reference or array of references on which the selector depends for computing - * its own return value. The memoize cache is preserved only as long as those - * dependant references remain the same. If getDependants returns a different - * reference(s), the cache is cleared and the selector value regenerated. - * - * @param {Function} selector Selector function. - * @param {Function} getDependants Dependant getter returning an immutable - * reference or array of reference used in - * cache bust consideration. - * - * @return {Function} Memoized selector. - */ -/* harmony default export */ function rememo(selector, getDependants ) { - var rootCache, getCache; - - // Use object source as dependant if getter not provided - if ( ! getDependants ) { - getDependants = arrayOf; - } - - /** - * Returns the root cache. If WeakMap is supported, this is assigned to the - * root WeakMap cache set, otherwise it is a shared instance of the default - * cache object. - * - * @return {(WeakMap|Object)} Root cache object. - */ - function getRootCache() { - return rootCache; - } - - /** - * Returns the cache for a given dependants array. When possible, a WeakMap - * will be used to create a unique cache for each set of dependants. This - * is feasible due to the nature of WeakMap in allowing garbage collection - * to occur on entries where the key object is no longer referenced. Since - * WeakMap requires the key to be an object, this is only possible when the - * dependant is object-like. The root cache is created as a hierarchy where - * each top-level key is the first entry in a dependants set, the value a - * WeakMap where each key is the next dependant, and so on. This continues - * so long as the dependants are object-like. If no dependants are object- - * like, then the cache is shared across all invocations. - * - * @see isObjectLike - * - * @param {Array} dependants Selector dependants. - * - * @return {Object} Cache object. - */ - function getWeakMapCache( dependants ) { - var caches = rootCache, - isUniqueByDependants = true, - i, dependant, map, cache; - - for ( i = 0; i < dependants.length; i++ ) { - dependant = dependants[ i ]; - - // Can only compose WeakMap from object-like key. - if ( ! isObjectLike( dependant ) ) { - isUniqueByDependants = false; - break; - } - - // Does current segment of cache already have a WeakMap? - if ( caches.has( dependant ) ) { - // Traverse into nested WeakMap. - caches = caches.get( dependant ); - } else { - // Create, set, and traverse into a new one. - map = new WeakMap(); - caches.set( dependant, map ); - caches = map; - } - } - - // We use an arbitrary (but consistent) object as key for the last item - // in the WeakMap to serve as our running cache. - if ( ! caches.has( LEAF_KEY ) ) { - cache = createCache(); - cache.isUniqueByDependants = isUniqueByDependants; - caches.set( LEAF_KEY, cache ); - } - - return caches.get( LEAF_KEY ); - } - - // Assign cache handler by availability of WeakMap - getCache = hasWeakMap ? getWeakMapCache : getRootCache; - - /** - * Resets root memoization cache. - */ - function clear() { - rootCache = hasWeakMap ? new WeakMap() : createCache(); - } - - // eslint-disable-next-line jsdoc/check-param-names - /** - * The augmented selector call, considering first whether dependants have - * changed before passing it to underlying memoize function. - * - * @param {Object} source Source object for derivation. - * @param {...*} extraArgs Additional arguments to pass to selector. - * - * @return {*} Selector result. - */ - function callSelector( /* source, ...extraArgs */ ) { - var len = arguments.length, - cache, node, i, args, dependants; - - // Create copy of arguments (avoid leaking deoptimization). - args = new Array( len ); - for ( i = 0; i < len; i++ ) { - args[ i ] = arguments[ i ]; - } - - dependants = getDependants.apply( null, args ); - cache = getCache( dependants ); - - // If not guaranteed uniqueness by dependants (primitive type or lack - // of WeakMap support), shallow compare against last dependants and, if - // references have changed, destroy cache to recalculate result. - if ( ! cache.isUniqueByDependants ) { - if ( cache.lastDependants && ! isShallowEqual( dependants, cache.lastDependants, 0 ) ) { - cache.clear(); - } - - cache.lastDependants = dependants; - } - - node = cache.head; - while ( node ) { - // Check whether node arguments match arguments - if ( ! isShallowEqual( node.args, args, 1 ) ) { - node = node.next; - continue; - } - - // At this point we can assume we've found a match - - // Surface matched node to head if not already - if ( node !== cache.head ) { - // Adjust siblings to point to each other. - node.prev.next = node.next; - if ( node.next ) { - node.next.prev = node.prev; - } - - node.next = cache.head; - node.prev = null; - cache.head.prev = node; - cache.head = node; - } - - // Return immediately - return node.val; - } - - // No cached value found. Continue to insertion phase: - - node = { - // Generate the result from original function - val: selector.apply( null, args ), - }; - - // Avoid including the source object in the cache. - args[ 0 ] = null; - node.args = args; - - // Don't need to check whether node is already head, since it would - // have been returned above already if it was - - // Shift existing head down list - if ( cache.head ) { - cache.head.prev = node; - node.next = cache.head; - } - - cache.head = node; - - return node.val; - } - - callSelector.getDependants = getDependants; - callSelector.clear = clear; - clear(); - - return callSelector; -} - // EXTERNAL MODULE: ./node_modules/equivalent-key-map/equivalent-key-map.js -var equivalent_key_map = __webpack_require__(2167); +var equivalent_key_map = __webpack_require__(3249); var equivalent_key_map_default = /*#__PURE__*/__webpack_require__.n(equivalent_key_map); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/queried-data/selectors.js /** @@ -3687,12 +4201,17 @@ */ +/** + * WordPress dependencies + */ + /** * Internal dependencies */ + /** * Cache of state keys to EquivalentKeyMap where the inner map tracks queries * to their resulting items set. WeakMap allows garbage collection on expired @@ -3700,8 +4219,8 @@ * * @type {WeakMap} */ - const queriedItemsCacheByState = new WeakMap(); + /** * Returns items for a given query, or null if the items are not known. * @@ -3710,10 +4229,7 @@ * * @return {?Array} Query items. */ - function getQueriedItemsUncached(state, query) { - var _state$queries, _state$queries$contex; - const { stableKey, page, @@ -3723,61 +4239,52 @@ context } = get_query_parts(query); let itemIds; - - if ((_state$queries = state.queries) !== null && _state$queries !== void 0 && (_state$queries$contex = _state$queries[context]) !== null && _state$queries$contex !== void 0 && _state$queries$contex[stableKey]) { - itemIds = state.queries[context][stableKey]; - } - + if (state.queries?.[context]?.[stableKey]) { + itemIds = state.queries[context][stableKey].itemIds; + } if (!itemIds) { return null; } - const startOffset = perPage === -1 ? 0 : (page - 1) * perPage; const endOffset = perPage === -1 ? itemIds.length : Math.min(startOffset + perPage, itemIds.length); const items = []; - for (let i = startOffset; i < endOffset; i++) { - var _state$items$context; - const itemId = itemIds[i]; - if (Array.isArray(include) && !include.includes(itemId)) { continue; - } // Having a target item ID doesn't guarantee that this object has been queried. - - - if (!((_state$items$context = state.items[context]) !== null && _state$items$context !== void 0 && _state$items$context.hasOwnProperty(itemId))) { + } + if (itemId === undefined) { + continue; + } + // Having a target item ID doesn't guarantee that this object has been queried. + if (!state.items[context]?.hasOwnProperty(itemId)) { return null; } - const item = state.items[context][itemId]; let filteredItem; - if (Array.isArray(fields)) { filteredItem = {}; - for (let f = 0; f < fields.length; f++) { const field = fields[f].split('.'); - const value = (0,external_lodash_namespaceObject.get)(item, field); - (0,external_lodash_namespaceObject.set)(filteredItem, field, value); + let value = item; + field.forEach(fieldName => { + value = value?.[fieldName]; + }); + setNestedValue(filteredItem, field, value); } } else { - var _state$itemIsComplete; - // If expecting a complete item, validate that completeness, or // otherwise abort. - if (!((_state$itemIsComplete = state.itemIsComplete[context]) !== null && _state$itemIsComplete !== void 0 && _state$itemIsComplete[itemId])) { + if (!state.itemIsComplete[context]?.[itemId]) { return null; } - filteredItem = item; } - items.push(filteredItem); } - return items; } + /** * Returns items for a given query, or null if the items are not known. Caches * result both per state (by reference) and per query (by deep equality). @@ -3791,15 +4298,10 @@ * * @return {?Array} Query items. */ - - -const getQueriedItems = rememo(function (state) { - let query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; +const getQueriedItems = (0,external_wp_data_namespaceObject.createSelector)((state, query = {}) => { let queriedItemsCache = queriedItemsCacheByState.get(state); - if (queriedItemsCache) { const queriedItems = queriedItemsCache.get(query); - if (queriedItems !== undefined) { return queriedItems; } @@ -3807,11 +4309,38 @@ queriedItemsCache = new (equivalent_key_map_default())(); queriedItemsCacheByState.set(state, queriedItemsCache); } - const items = getQueriedItemsUncached(state, query); queriedItemsCache.set(query, items); return items; }); +function getQueriedTotalItems(state, query = {}) { + var _state$queries$contex; + const { + stableKey, + context + } = get_query_parts(query); + return (_state$queries$contex = state.queries?.[context]?.[stableKey]?.meta?.totalItems) !== null && _state$queries$contex !== void 0 ? _state$queries$contex : null; +} +function getQueriedTotalPages(state, query = {}) { + var _state$queries$contex2; + const { + stableKey, + context + } = get_query_parts(query); + return (_state$queries$contex2 = state.queries?.[context]?.[stableKey]?.meta?.totalPages) !== null && _state$queries$contex2 !== void 0 ? _state$queries$contex2 : null; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/is-numeric-id.js +/** + * Checks argument to determine if it's a numeric ID. + * For example, '123' is a numeric ID, but '123abc' is not. + * + * @param {any} id the argument to determine if it's a numeric ID. + * @return {boolean} true if the string is a numeric ID, false otherwise. + */ +function isNumericID(id) { + return /^\s*\d+\s*$/.test(id); +} ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/is-raw-attribute.js /** @@ -3828,11 +4357,6 @@ ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/selectors.js /** - * External dependencies - */ - - -/** * WordPress dependencies */ @@ -3847,6 +4371,19 @@ +// This is an incomplete, high-level approximation of the State type. +// It makes the selectors slightly more safe, but is intended to evolve +// into a more detailed representation over time. +// See https://github.com/WordPress/gutenberg/pull/40025#discussion_r865410589 for more context. + +/** + * HTTP Query parameters sent with the API request to fetch the entity records. + */ + +/** + * Arguments for EntityRecord selectors. + */ + /** * Shared reference to an empty object for cases where it is important to avoid * returning a new object reference on every invocation, as in a connected or @@ -3854,32 +4391,31 @@ * This should be used as a last resort, since the normalized data should be * maintained by the reducer result in state. */ - const EMPTY_OBJECT = {}; + /** * Returns true if a request is in progress for embed preview data, or false * otherwise. * - * @param {Object} state Data state. - * @param {string} url URL the preview would be for. - * - * @return {boolean} Whether a request is in progress for an embed preview. - */ - + * @param state Data state. + * @param url URL the preview would be for. + * + * @return Whether a request is in progress for an embed preview. + */ const isRequestingEmbedPreview = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, url) => { return select(STORE_NAME).isResolving('getEmbedPreview', [url]); }); + /** * Returns all available authors. * * @deprecated since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead. * - * @param {Object} state Data state. - * @param {Object|undefined} query Optional object of query parameters to - * include with request. - * @return {Array} Authors list. - */ - + * @param state Data state. + * @param query Optional object of query parameters to + * include with request. For valid query parameters see the [Users page](https://developer.wordpress.org/rest-api/reference/users/) in the REST API Handbook and see the arguments for [List Users](https://developer.wordpress.org/rest-api/reference/users/#list-users) and [Retrieve a User](https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user). + * @return Authors list. + */ function getAuthors(state, query) { external_wp_deprecated_default()("select( 'core' ).getAuthors()", { since: '5.9', @@ -3888,40 +4424,41 @@ const path = (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/users/?who=authors&per_page=100', query); return getUserQueryResults(state, path); } + /** * Returns the current user. * - * @param {Object} state Data state. - * - * @return {Object} Current user object. - */ - + * @param state Data state. + * + * @return Current user object. + */ function getCurrentUser(state) { return state.currentUser; } + /** * Returns all the users returned by a query ID. * - * @param {Object} state Data state. - * @param {string} queryID Query ID. - * - * @return {Array} Users list. - */ - -const getUserQueryResults = rememo((state, queryID) => { - const queryResults = state.users.queries[queryID]; - return (0,external_lodash_namespaceObject.map)(queryResults, id => state.users.byId[id]); + * @param state Data state. + * @param queryID Query ID. + * + * @return Users list. + */ +const getUserQueryResults = (0,external_wp_data_namespaceObject.createSelector)((state, queryID) => { + var _state$users$queries$; + const queryResults = (_state$users$queries$ = state.users.queries[queryID]) !== null && _state$users$queries$ !== void 0 ? _state$users$queries$ : []; + return queryResults.map(id => state.users.byId[id]); }, (state, queryID) => [state.users.queries[queryID], state.users.byId]); + /** * Returns the loaded entities for the given kind. * * @deprecated since WordPress 6.0. Use getEntitiesConfig instead - * @param {Object} state Data state. - * @param {string} kind Entity kind. - * - * @return {Array} Array of entities with config matching kind. - */ - + * @param state Data state. + * @param kind Entity kind. + * + * @return Array of entities with config matching kind. + */ function getEntitiesByKind(state, kind) { external_wp_deprecated_default()("wp.data.select( 'core' ).getEntitiesByKind()", { since: '6.0', @@ -3929,31 +4466,26 @@ }); return getEntitiesConfig(state, kind); } + /** * Returns the loaded entities for the given kind. * - * @param {Object} state Data state. - * @param {string} kind Entity kind. - * - * @return {Array} Array of entities with config matching kind. - */ - -function getEntitiesConfig(state, kind) { - return (0,external_lodash_namespaceObject.filter)(state.entities.config, { - kind - }); -} + * @param state Data state. + * @param kind Entity kind. + * + * @return Array of entities with config matching kind. + */ +const getEntitiesConfig = (0,external_wp_data_namespaceObject.createSelector)((state, kind) => state.entities.config.filter(entity => entity.kind === kind), (state, kind) => state.entities.config); /** * Returns the entity config given its kind and name. * * @deprecated since WordPress 6.0. Use getEntityConfig instead - * @param {Object} state Data state. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * - * @return {Object} Entity config - */ - + * @param state Data state. + * @param kind Entity kind. + * @param name Entity name. + * + * @return Entity config + */ function getEntity(state, kind, name) { external_wp_deprecated_default()("wp.data.select( 'core' ).getEntity()", { since: '6.0', @@ -3961,174 +4493,261 @@ }); return getEntityConfig(state, kind, name); } + /** * Returns the entity config given its kind and name. * - * @param {Object} state Data state. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * - * @return {Object} Entity config - */ - + * @param state Data state. + * @param kind Entity kind. + * @param name Entity name. + * + * @return Entity config + */ function getEntityConfig(state, kind, name) { - return (0,external_lodash_namespaceObject.find)(state.entities.config, { - kind, - name - }); -} + return state.entities.config?.find(config => config.kind === kind && config.name === name); +} + +/** + * GetEntityRecord is declared as a *callable interface* with + * two signatures to work around the fact that TypeScript doesn't + * allow currying generic functions: + * + * ```ts + * type CurriedState = F extends ( state: any, ...args: infer P ) => infer R + * ? ( ...args: P ) => R + * : F; + * type Selector = ( + * state: any, + * kind: K, + * key: K extends string ? 'string value' : false + * ) => K; + * type BadlyInferredSignature = CurriedState< Selector > + * // BadlyInferredSignature evaluates to: + * // (kind: string number, key: false | "string value") => string number + * ``` + * + * The signature without the state parameter shipped as CurriedSignature + * is used in the return value of `select( coreStore )`. + * + * See https://github.com/WordPress/gutenberg/pull/41578 for more details. + */ + /** * Returns the Entity's record object by key. Returns `null` if the value is not * yet received, undefined if the value entity is known to not exist, or the * entity object if it exists and is received. * - * @param {Object} state State tree - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} key Record's key - * @param {?Object} query Optional query. - * - * @return {Object|undefined} Record. - */ - -const getEntityRecord = rememo((state, kind, name, key, query) => { - var _query$context, _queriedState$items$c; - - const queriedState = (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData']); - + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param key Record's key + * @param query Optional query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]". + * + * @return Record. + */ +const getEntityRecord = (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, key, query) => { + var _query$context; + const queriedState = state.entities.records?.[kind]?.[name]?.queriedData; if (!queriedState) { return undefined; } - - const context = (_query$context = query === null || query === void 0 ? void 0 : query.context) !== null && _query$context !== void 0 ? _query$context : 'default'; - + const context = (_query$context = query?.context) !== null && _query$context !== void 0 ? _query$context : 'default'; if (query === undefined) { - var _queriedState$itemIsC; - // If expecting a complete item, validate that completeness. - if (!((_queriedState$itemIsC = queriedState.itemIsComplete[context]) !== null && _queriedState$itemIsC !== void 0 && _queriedState$itemIsC[key])) { + if (!queriedState.itemIsComplete[context]?.[key]) { return undefined; } - return queriedState.items[context][key]; } - - const item = (_queriedState$items$c = queriedState.items[context]) === null || _queriedState$items$c === void 0 ? void 0 : _queriedState$items$c[key]; - + const item = queriedState.items[context]?.[key]; if (item && query._fields) { var _getNormalizedCommaSe; - const filteredItem = {}; const fields = (_getNormalizedCommaSe = get_normalized_comma_separable(query._fields)) !== null && _getNormalizedCommaSe !== void 0 ? _getNormalizedCommaSe : []; - for (let f = 0; f < fields.length; f++) { const field = fields[f].split('.'); - const value = (0,external_lodash_namespaceObject.get)(item, field); - (0,external_lodash_namespaceObject.set)(filteredItem, field, value); + let value = item; + field.forEach(fieldName => { + value = value?.[fieldName]; + }); + setNestedValue(filteredItem, field, value); } - return filteredItem; } - return item; }, (state, kind, name, recordId, query) => { var _query$context2; - - const context = (_query$context2 = query === null || query === void 0 ? void 0 : query.context) !== null && _query$context2 !== void 0 ? _query$context2 : 'default'; - return [(0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'items', context, recordId]), (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'itemIsComplete', context, recordId])]; + const context = (_query$context2 = query?.context) !== null && _query$context2 !== void 0 ? _query$context2 : 'default'; + return [state.entities.records?.[kind]?.[name]?.queriedData?.items[context]?.[recordId], state.entities.records?.[kind]?.[name]?.queriedData?.itemIsComplete[context]?.[recordId]]; }); + +/** + * Normalizes `recordKey`s that look like numeric IDs to numbers. + * + * @param args EntityRecordArgs the selector arguments. + * @return EntityRecordArgs the normalized arguments. + */ +getEntityRecord.__unstableNormalizeArgs = args => { + const newArgs = [...args]; + const recordKey = newArgs?.[2]; + + // If recordKey looks to be a numeric ID then coerce to number. + newArgs[2] = isNumericID(recordKey) ? Number(recordKey) : recordKey; + return newArgs; +}; + /** * Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity records from the API if the entity record isn't available in the local state. * - * @param {Object} state State tree - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} key Record's key - * - * @return {Object|null} Record. - */ - + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param key Record's key + * + * @return Record. + */ function __experimentalGetEntityRecordNoResolver(state, kind, name, key) { return getEntityRecord(state, kind, name, key); } + /** * Returns the entity's record object by key, * with its attributes mapped to their raw values. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} key Record's key. - * - * @return {Object?} Object with the entity's raw attributes. - */ - -const getRawEntityRecord = rememo((state, kind, name, key) => { + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param key Record's key. + * + * @return Object with the entity's raw attributes. + */ +const getRawEntityRecord = (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, key) => { const record = getEntityRecord(state, kind, name, key); return record && Object.keys(record).reduce((accumulator, _key) => { if (isRawAttribute(getEntityConfig(state, kind, name), _key)) { + var _record$_key$raw; // Because edits are the "raw" attribute values, // we return those from record selectors to make rendering, // comparisons, and joins with edits easier. - accumulator[_key] = (0,external_lodash_namespaceObject.get)(record[_key], 'raw', record[_key]); + accumulator[_key] = (_record$_key$raw = record[_key]?.raw) !== null && _record$_key$raw !== void 0 ? _record$_key$raw : record[_key]; } else { accumulator[_key] = record[_key]; } - return accumulator; }, {}); }, (state, kind, name, recordId, query) => { var _query$context3; - - const context = (_query$context3 = query === null || query === void 0 ? void 0 : query.context) !== null && _query$context3 !== void 0 ? _query$context3 : 'default'; - return [state.entities.config, (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'items', context, recordId]), (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'itemIsComplete', context, recordId])]; + const context = (_query$context3 = query?.context) !== null && _query$context3 !== void 0 ? _query$context3 : 'default'; + return [state.entities.config, state.entities.records?.[kind]?.[name]?.queriedData?.items[context]?.[recordId], state.entities.records?.[kind]?.[name]?.queriedData?.itemIsComplete[context]?.[recordId]]; }); + /** * Returns true if records have been received for the given set of parameters, * or false otherwise. * - * @param {Object} state State tree - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {?Object} query Optional terms query. - * - * @return {boolean} Whether entity records have been received. - */ - + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param query Optional terms query. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + * + * @return Whether entity records have been received. + */ function hasEntityRecords(state, kind, name, query) { return Array.isArray(getEntityRecords(state, kind, name, query)); } + +/** + * GetEntityRecord is declared as a *callable interface* with + * two signatures to work around the fact that TypeScript doesn't + * allow currying generic functions. + * + * @see GetEntityRecord + * @see https://github.com/WordPress/gutenberg/pull/41578 + */ + /** * Returns the Entity's records. * - * @param {Object} state State tree - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {?Object} query Optional terms query. - * - * @return {?Array} Records. - */ - -function getEntityRecords(state, kind, name, query) { + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param query Optional terms query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + * + * @return Records. + */ +const getEntityRecords = (state, kind, name, query) => { + // Queried data state is prepopulated for all known entities. If this is not + // assigned for the given parameters, then it is known to not exist. + const queriedState = state.entities.records?.[kind]?.[name]?.queriedData; + if (!queriedState) { + return null; + } + return getQueriedItems(queriedState, query); +}; + +/** + * Returns the Entity's total available records for a given query (ignoring pagination). + * + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param query Optional terms query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + * + * @return number | null. + */ +const getEntityRecordsTotalItems = (state, kind, name, query) => { // Queried data state is prepopulated for all known entities. If this is not // assigned for the given parameters, then it is known to not exist. - const queriedState = (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData']); - + const queriedState = state.entities.records?.[kind]?.[name]?.queriedData; + if (!queriedState) { + return null; + } + return getQueriedTotalItems(queriedState, query); +}; + +/** + * Returns the number of available pages for the given query. + * + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param query Optional terms query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s". + * + * @return number | null. + */ +const getEntityRecordsTotalPages = (state, kind, name, query) => { + // Queried data state is prepopulated for all known entities. If this is not + // assigned for the given parameters, then it is known to not exist. + const queriedState = state.entities.records?.[kind]?.[name]?.queriedData; if (!queriedState) { return null; } - - return getQueriedItems(queriedState, query); -} -/** - * Returns the list of dirty entity records. - * - * @param {Object} state State tree. - * - * @return {[{ title: string, key: string, name: string, kind: string }]} The list of updated records - */ - -const __experimentalGetDirtyEntityRecords = rememo(state => { + if (query.per_page === -1) { + return 1; + } + const totalItems = getQueriedTotalItems(queriedState, query); + if (!totalItems) { + return totalItems; + } + // If `per_page` is not set and the query relies on the defaults of the + // REST endpoint, get the info from query's meta. + if (!query.per_page) { + return getQueriedTotalPages(queriedState, query); + } + return Math.ceil(totalItems / query.per_page); +}; +/** + * Returns the list of dirty entity records. + * + * @param state State tree. + * + * @return The list of updated records + */ +const __experimentalGetDirtyEntityRecords = (0,external_wp_data_namespaceObject.createSelector)(state => { const { entities: { records @@ -4137,21 +4756,19 @@ const dirtyRecords = []; Object.keys(records).forEach(kind => { Object.keys(records[kind]).forEach(name => { - const primaryKeys = Object.keys(records[kind][name].edits).filter(primaryKey => // The entity record must exist (not be deleted), + const primaryKeys = Object.keys(records[kind][name].edits).filter(primaryKey => + // The entity record must exist (not be deleted), // and it must have edits. getEntityRecord(state, kind, name, primaryKey) && hasEditsForEntityRecord(state, kind, name, primaryKey)); - if (primaryKeys.length) { const entityConfig = getEntityConfig(state, kind, name); primaryKeys.forEach(primaryKey => { - var _entityConfig$getTitl; - const entityRecord = getEditedEntityRecord(state, kind, name, primaryKey); dirtyRecords.push({ // We avoid using primaryKey because it's transformed into a string // when it's used as an object key. - key: entityRecord[entityConfig.key || DEFAULT_ENTITY_KEY], - title: (entityConfig === null || entityConfig === void 0 ? void 0 : (_entityConfig$getTitl = entityConfig.getTitle) === null || _entityConfig$getTitl === void 0 ? void 0 : _entityConfig$getTitl.call(entityConfig, entityRecord)) || '', + key: entityRecord ? entityRecord[entityConfig.key || DEFAULT_ENTITY_KEY] : undefined, + title: entityConfig?.getTitle?.(entityRecord) || '', name, kind }); @@ -4161,15 +4778,15 @@ }); return dirtyRecords; }, state => [state.entities.records]); + /** * Returns the list of entities currently being saved. * - * @param {Object} state State tree. - * - * @return {[{ title: string, key: string, name: string, kind: string }]} The list of records being saved. - */ - -const __experimentalGetEntitiesBeingSaved = rememo(state => { + * @param state State tree. + * + * @return The list of records being saved. + */ +const __experimentalGetEntitiesBeingSaved = (0,external_wp_data_namespaceObject.createSelector)(state => { const { entities: { records @@ -4179,18 +4796,15 @@ Object.keys(records).forEach(kind => { Object.keys(records[kind]).forEach(name => { const primaryKeys = Object.keys(records[kind][name].saving).filter(primaryKey => isSavingEntityRecord(state, kind, name, primaryKey)); - if (primaryKeys.length) { const entityConfig = getEntityConfig(state, kind, name); primaryKeys.forEach(primaryKey => { - var _entityConfig$getTitl2; - const entityRecord = getEditedEntityRecord(state, kind, name, primaryKey); recordsBeingSaved.push({ // We avoid using primaryKey because it's transformed into a string // when it's used as an object key. - key: entityRecord[entityConfig.key || DEFAULT_ENTITY_KEY], - title: (entityConfig === null || entityConfig === void 0 ? void 0 : (_entityConfig$getTitl2 = entityConfig.getTitle) === null || _entityConfig$getTitl2 === void 0 ? void 0 : _entityConfig$getTitl2.call(entityConfig, entityRecord)) || '', + key: entityRecord ? entityRecord[entityConfig.key || DEFAULT_ENTITY_KEY] : undefined, + title: entityConfig?.getTitle?.(entityRecord) || '', name, kind }); @@ -4200,20 +4814,21 @@ }); return recordsBeingSaved; }, state => [state.entities.records]); + /** * Returns the specified entity record's edits. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {Object?} The entity record's edits. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return The entity record's edits. + */ function getEntityRecordEdits(state, kind, name, recordId) { - return (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'edits', recordId]); -} + return state.entities.records?.[kind]?.[name]?.edits?.[recordId]; +} + /** * Returns the specified entity record's non transient edits. * @@ -4221,251 +4836,258 @@ * are not considered for change detection. * They are defined in the entity's config. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {Object?} The entity record's non transient edits. - */ - -const getEntityRecordNonTransientEdits = rememo((state, kind, name, recordId) => { + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return The entity record's non transient edits. + */ +const getEntityRecordNonTransientEdits = (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, recordId) => { const { transientEdits } = getEntityConfig(state, kind, name) || {}; const edits = getEntityRecordEdits(state, kind, name, recordId) || {}; - if (!transientEdits) { return edits; } - return Object.keys(edits).reduce((acc, key) => { if (!transientEdits[key]) { acc[key] = edits[key]; } - return acc; }, {}); -}, (state, kind, name, recordId) => [state.entities.config, (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'edits', recordId])]); +}, (state, kind, name, recordId) => [state.entities.config, state.entities.records?.[kind]?.[name]?.edits?.[recordId]]); + /** * Returns true if the specified entity record has edits, * and false otherwise. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number|string} recordId Record ID. - * - * @return {boolean} Whether the entity record has edits or not. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return Whether the entity record has edits or not. + */ function hasEditsForEntityRecord(state, kind, name, recordId) { return isSavingEntityRecord(state, kind, name, recordId) || Object.keys(getEntityRecordNonTransientEdits(state, kind, name, recordId)).length > 0; } + /** * Returns the specified entity record, merged with its edits. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number|string} recordId Record ID. - * - * @return {Object?} The entity record, merged with its edits. - */ - -const getEditedEntityRecord = rememo((state, kind, name, recordId) => ({ ...getRawEntityRecord(state, kind, name, recordId), - ...getEntityRecordEdits(state, kind, name, recordId) -}), (state, kind, name, recordId, query) => { + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return The entity record, merged with its edits. + */ +const getEditedEntityRecord = (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, recordId) => { + const raw = getRawEntityRecord(state, kind, name, recordId); + const edited = getEntityRecordEdits(state, kind, name, recordId); + // Never return a non-falsy empty object. Unfortunately we can't return + // undefined or null because we were previously returning an empty + // object, so trying to read properties from the result would throw. + // Using false here is a workaround to avoid breaking changes. + if (!raw && !edited) { + return false; + } + return { + ...raw, + ...edited + }; +}, (state, kind, name, recordId, query) => { var _query$context4; - - const context = (_query$context4 = query === null || query === void 0 ? void 0 : query.context) !== null && _query$context4 !== void 0 ? _query$context4 : 'default'; - return [state.entities.config, (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'items', context, recordId]), (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'queriedData', 'itemIsComplete', context, recordId]), (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'edits', recordId])]; + const context = (_query$context4 = query?.context) !== null && _query$context4 !== void 0 ? _query$context4 : 'default'; + return [state.entities.config, state.entities.records?.[kind]?.[name]?.queriedData.items[context]?.[recordId], state.entities.records?.[kind]?.[name]?.queriedData.itemIsComplete[context]?.[recordId], state.entities.records?.[kind]?.[name]?.edits?.[recordId]]; }); + /** * Returns true if the specified entity record is autosaving, and false otherwise. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {boolean} Whether the entity record is autosaving or not. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return Whether the entity record is autosaving or not. + */ function isAutosavingEntityRecord(state, kind, name, recordId) { + var _state$entities$recor; const { pending, isAutosave - } = (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'saving', recordId], {}); + } = (_state$entities$recor = state.entities.records?.[kind]?.[name]?.saving?.[recordId]) !== null && _state$entities$recor !== void 0 ? _state$entities$recor : {}; return Boolean(pending && isAutosave); } + /** * Returns true if the specified entity record is saving, and false otherwise. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number|string} recordId Record ID. - * - * @return {boolean} Whether the entity record is saving or not. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return Whether the entity record is saving or not. + */ function isSavingEntityRecord(state, kind, name, recordId) { - return (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'saving', recordId, 'pending'], false); -} + var _state$entities$recor2; + return (_state$entities$recor2 = state.entities.records?.[kind]?.[name]?.saving?.[recordId]?.pending) !== null && _state$entities$recor2 !== void 0 ? _state$entities$recor2 : false; +} + /** * Returns true if the specified entity record is deleting, and false otherwise. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {boolean} Whether the entity record is deleting or not. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return Whether the entity record is deleting or not. + */ function isDeletingEntityRecord(state, kind, name, recordId) { - return (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'deleting', recordId, 'pending'], false); -} + var _state$entities$recor3; + return (_state$entities$recor3 = state.entities.records?.[kind]?.[name]?.deleting?.[recordId]?.pending) !== null && _state$entities$recor3 !== void 0 ? _state$entities$recor3 : false; +} + /** * Returns the specified entity record's last save error. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {Object?} The entity record's save error. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return The entity record's save error. + */ function getLastEntitySaveError(state, kind, name, recordId) { - return (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'saving', recordId, 'error']); -} + return state.entities.records?.[kind]?.[name]?.saving?.[recordId]?.error; +} + /** * Returns the specified entity record's last delete error. * - * @param {Object} state State tree. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number} recordId Record ID. - * - * @return {Object?} The entity record's save error. - */ - + * @param state State tree. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record ID. + * + * @return The entity record's save error. + */ function getLastEntityDeleteError(state, kind, name, recordId) { - return (0,external_lodash_namespaceObject.get)(state.entities.records, [kind, name, 'deleting', recordId, 'error']); -} -/** - * Returns the current undo offset for the - * entity records edits history. The offset - * represents how many items from the end - * of the history stack we are at. 0 is the - * last edit, -1 is the second last, and so on. - * - * @param {Object} state State tree. - * - * @return {number} The current undo offset. - */ - -function getCurrentUndoOffset(state) { - return state.undo.offset; -} + return state.entities.records?.[kind]?.[name]?.deleting?.[recordId]?.error; +} + /** * Returns the previous edit from the current undo offset * for the entity records edits history, if any. * - * @param {Object} state State tree. - * - * @return {Object?} The edit. - */ - - + * @deprecated since 6.3 + * + * @param state State tree. + * + * @return The edit. + */ function getUndoEdit(state) { - return state.undo[state.undo.length - 2 + getCurrentUndoOffset(state)]; -} + external_wp_deprecated_default()("select( 'core' ).getUndoEdit()", { + since: '6.3' + }); + return undefined; +} + /** * Returns the next edit from the current undo offset * for the entity records edits history, if any. * - * @param {Object} state State tree. - * - * @return {Object?} The edit. - */ - + * @deprecated since 6.3 + * + * @param state State tree. + * + * @return The edit. + */ function getRedoEdit(state) { - return state.undo[state.undo.length + getCurrentUndoOffset(state)]; -} + external_wp_deprecated_default()("select( 'core' ).getRedoEdit()", { + since: '6.3' + }); + return undefined; +} + /** * Returns true if there is a previous edit from the current undo offset * for the entity records edits history, and false otherwise. * - * @param {Object} state State tree. - * - * @return {boolean} Whether there is a previous edit or not. - */ - + * @param state State tree. + * + * @return Whether there is a previous edit or not. + */ function hasUndo(state) { - return Boolean(getUndoEdit(state)); -} + return state.undoManager.hasUndo(); +} + /** * Returns true if there is a next edit from the current undo offset * for the entity records edits history, and false otherwise. * - * @param {Object} state State tree. - * - * @return {boolean} Whether there is a next edit or not. - */ - + * @param state State tree. + * + * @return Whether there is a next edit or not. + */ function hasRedo(state) { - return Boolean(getRedoEdit(state)); -} + return state.undoManager.hasRedo(); +} + /** * Return the current theme. * - * @param {Object} state Data state. - * - * @return {Object} The current theme. - */ - + * @param state Data state. + * + * @return The current theme. + */ function getCurrentTheme(state) { + if (!state.currentTheme) { + return null; + } return getEntityRecord(state, 'root', 'theme', state.currentTheme); } + /** * Return the ID of the current global styles object. * - * @param {Object} state Data state. - * - * @return {string} The current global styles ID. - */ - + * @param state Data state. + * + * @return The current global styles ID. + */ function __experimentalGetCurrentGlobalStylesId(state) { return state.currentGlobalStylesId; } + /** * Return theme supports data in the index. * - * @param {Object} state Data state. - * - * @return {*} Index data. - */ - + * @param state Data state. + * + * @return Index data. + */ function getThemeSupports(state) { - var _getCurrentTheme$them, _getCurrentTheme; - - return (_getCurrentTheme$them = (_getCurrentTheme = getCurrentTheme(state)) === null || _getCurrentTheme === void 0 ? void 0 : _getCurrentTheme.theme_supports) !== null && _getCurrentTheme$them !== void 0 ? _getCurrentTheme$them : EMPTY_OBJECT; -} + var _getCurrentTheme$them; + return (_getCurrentTheme$them = getCurrentTheme(state)?.theme_supports) !== null && _getCurrentTheme$them !== void 0 ? _getCurrentTheme$them : EMPTY_OBJECT; +} + /** * Returns the embed preview for the given URL. * - * @param {Object} state Data state. - * @param {string} url Embedded URL. - * - * @return {*} Undefined if the preview has not been fetched, otherwise, the preview fetched from the embed preview API. - */ - + * @param state Data state. + * @param url Embedded URL. + * + * @return Undefined if the preview has not been fetched, otherwise, the preview fetched from the embed preview API. + */ function getEmbedPreview(state, url) { return state.embedPreviews[url]; } + /** * Determines if the returned preview is an oEmbed link fallback. * @@ -4473,22 +5095,20 @@ * We need to be able to determine if a URL is embeddable or not, based on what we * get back from the oEmbed preview API. * - * @param {Object} state Data state. - * @param {string} url Embedded URL. - * - * @return {boolean} Is the preview for the URL an oEmbed link fallback. - */ - + * @param state Data state. + * @param url Embedded URL. + * + * @return Is the preview for the URL an oEmbed link fallback. + */ function isPreviewEmbedFallback(state, url) { const preview = state.embedPreviews[url]; const oEmbedLinkCheck = '' + url + ''; - if (!preview) { return false; } - return preview.html === oEmbedLinkCheck; } + /** * Returns whether the current user can perform the given action on the given * REST resource. @@ -4498,19 +5118,19 @@ * * https://developer.wordpress.org/rest-api/reference/ * - * @param {Object} state Data state. - * @param {string} action Action to check. One of: 'create', 'read', 'update', 'delete'. - * @param {string} resource REST resource to check, e.g. 'media' or 'posts'. - * @param {string=} id Optional ID of the rest resource to check. - * - * @return {boolean|undefined} Whether or not the user can perform the action, + * @param state Data state. + * @param action Action to check. One of: 'create', 'read', 'update', 'delete'. + * @param resource REST resource to check, e.g. 'media' or 'posts'. + * @param id Optional ID of the rest resource to check. + * + * @return Whether or not the user can perform the action, * or `undefined` if the OPTIONS request is still being made. */ - function canUser(state, action, resource, id) { - const key = (0,external_lodash_namespaceObject.compact)([action, resource, id]).join('/'); - return (0,external_lodash_namespaceObject.get)(state, ['userPermissions', key]); -} + const key = [action, resource, id].filter(Boolean).join('/'); + return state.userPermissions[key]; +} + /** * Returns whether the current user can edit the given entity. * @@ -4519,74 +5139,69 @@ * * https://developer.wordpress.org/rest-api/reference/ * - * @param {Object} state Data state. - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {string} recordId Record's id. - * @return {boolean|undefined} Whether or not the user can edit, + * @param state Data state. + * @param kind Entity kind. + * @param name Entity name. + * @param recordId Record's id. + * @return Whether or not the user can edit, * or `undefined` if the OPTIONS request is still being made. */ - function canUserEditEntityRecord(state, kind, name, recordId) { const entityConfig = getEntityConfig(state, kind, name); - if (!entityConfig) { return false; } - const resource = entityConfig.__unstable_rest_base; return canUser(state, 'update', resource, recordId); } + /** * Returns the latest autosaves for the post. * * May return multiple autosaves since the backend stores one autosave per * author for each post. * - * @param {Object} state State tree. - * @param {string} postType The type of the parent post. - * @param {number} postId The id of the parent post. - * - * @return {?Array} An array of autosaves for the post, or undefined if there is none. - */ - + * @param state State tree. + * @param postType The type of the parent post. + * @param postId The id of the parent post. + * + * @return An array of autosaves for the post, or undefined if there is none. + */ function getAutosaves(state, postType, postId) { return state.autosaves[postId]; } + /** * Returns the autosave for the post and author. * - * @param {Object} state State tree. - * @param {string} postType The type of the parent post. - * @param {number} postId The id of the parent post. - * @param {number} authorId The id of the author. - * - * @return {?Object} The autosave for the post and author. - */ - + * @param state State tree. + * @param postType The type of the parent post. + * @param postId The id of the parent post. + * @param authorId The id of the author. + * + * @return The autosave for the post and author. + */ function getAutosave(state, postType, postId, authorId) { if (authorId === undefined) { return; } - const autosaves = state.autosaves[postId]; - return (0,external_lodash_namespaceObject.find)(autosaves, { - author: authorId - }); -} + return autosaves?.find(autosave => autosave.author === authorId); +} + /** * Returns true if the REST request for autosaves has completed. * - * @param {Object} state State tree. - * @param {string} postType The type of the parent post. - * @param {number} postId The id of the parent post. - * - * @return {boolean} True if the REST request was completed. False otherwise. - */ - + * @param state State tree. + * @param postType The type of the parent post. + * @param postId The id of the parent post. + * + * @return True if the REST request was completed. False otherwise. + */ const hasFetchedAutosaves = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (state, postType, postId) => { return select(STORE_NAME).hasFinishedResolution('getAutosaves', [postType, postId]); }); + /** * Returns a new reference when edited values have changed. This is useful in * inferring where an edit has been made between states by comparison of the @@ -4601,90 +5216,254 @@ * ); * ``` * - * @param {Object} state Editor state. - * - * @return {*} A value whose reference will change only when an edit occurs. - */ - -const getReferenceByDistinctEdits = rememo(() => [], state => [state.undo.length, state.undo.offset, state.undo.flattenedUndo]); + * @param state Editor state. + * + * @return A value whose reference will change only when an edit occurs. + */ +function getReferenceByDistinctEdits(state) { + return state.editsReference; +} + /** * Retrieve the frontend template used for a given link. * - * @param {Object} state Editor state. - * @param {string} link Link. - * - * @return {Object?} The template record. - */ - + * @param state Editor state. + * @param link Link. + * + * @return The template record. + */ function __experimentalGetTemplateForLink(state, link) { const records = getEntityRecords(state, 'postType', 'wp_template', { 'find-template': link }); - const template = records !== null && records !== void 0 && records.length ? records[0] : null; - - if (template) { - return getEditedEntityRecord(state, 'postType', 'wp_template', template.id); - } - - return template; -} + if (records?.length) { + return getEditedEntityRecord(state, 'postType', 'wp_template', records[0].id); + } + return null; +} + /** * Retrieve the current theme's base global styles * - * @param {Object} state Editor state. - * - * @return {Object|null} The Global Styles object. - */ - + * @param state Editor state. + * + * @return The Global Styles object. + */ function __experimentalGetCurrentThemeBaseGlobalStyles(state) { const currentTheme = getCurrentTheme(state); - if (!currentTheme) { return null; } - return state.themeBaseGlobalStyles[currentTheme.stylesheet]; } + /** * Return the ID of the current global styles object. * - * @param {Object} state Data state. - * - * @return {string|null} The current global styles ID. - */ - + * @param state Data state. + * + * @return The current global styles ID. + */ function __experimentalGetCurrentThemeGlobalStylesVariations(state) { const currentTheme = getCurrentTheme(state); - if (!currentTheme) { return null; } - return state.themeGlobalStyleVariations[currentTheme.stylesheet]; } + /** * Retrieve the list of registered block patterns. * - * @param {Object} state Data state. - * - * @return {Array} Block pattern list. - */ - + * @param state Data state. + * + * @return Block pattern list. + */ function getBlockPatterns(state) { return state.blockPatterns; } + /** * Retrieve the list of registered block pattern categories. * - * @param {Object} state Data state. - * - * @return {Array} Block pattern category list. - */ - + * @param state Data state. + * + * @return Block pattern category list. + */ function getBlockPatternCategories(state) { return state.blockPatternCategories; } +/** + * Retrieve the registered user pattern categories. + * + * @param state Data state. + * + * @return User patterns category array. + */ + +function getUserPatternCategories(state) { + return state.userPatternCategories; +} + +/** + * Returns the revisions of the current global styles theme. + * + * @deprecated since WordPress 6.5.0. Callers should use `select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )` instead, where `recordKey` is the id of the global styles parent post. + * + * @param state Data state. + * + * @return The current global styles. + */ +function getCurrentThemeGlobalStylesRevisions(state) { + external_wp_deprecated_default()("select( 'core' ).getCurrentThemeGlobalStylesRevisions()", { + since: '6.5.0', + alternative: "select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )" + }); + const currentGlobalStylesId = __experimentalGetCurrentGlobalStylesId(state); + if (!currentGlobalStylesId) { + return null; + } + return state.themeGlobalStyleRevisions[currentGlobalStylesId]; +} + +/** + * Returns the default template use to render a given query. + * + * @param state Data state. + * @param query Query. + * + * @return The default template id for the given query. + */ +function getDefaultTemplateId(state, query) { + return state.defaultTemplates[JSON.stringify(query)]; +} + +/** + * Returns an entity's revisions. + * + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param recordKey The key of the entity record whose revisions you want to fetch. + * @param query Optional query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [Entity kind]". + * + * @return Record. + */ +const getRevisions = (state, kind, name, recordKey, query) => { + const queriedStateRevisions = state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]; + if (!queriedStateRevisions) { + return null; + } + return getQueriedItems(queriedStateRevisions, query); +}; + +/** + * Returns a single, specific revision of a parent entity. + * + * @param state State tree + * @param kind Entity kind. + * @param name Entity name. + * @param recordKey The key of the entity record whose revisions you want to fetch. + * @param revisionKey The revision's key. + * @param query Optional query. If requesting specific + * fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [entity kind]". + * + * @return Record. + */ +const getRevision = (0,external_wp_data_namespaceObject.createSelector)((state, kind, name, recordKey, revisionKey, query) => { + var _query$context5; + const queriedState = state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]; + if (!queriedState) { + return undefined; + } + const context = (_query$context5 = query?.context) !== null && _query$context5 !== void 0 ? _query$context5 : 'default'; + if (query === undefined) { + // If expecting a complete item, validate that completeness. + if (!queriedState.itemIsComplete[context]?.[revisionKey]) { + return undefined; + } + return queriedState.items[context][revisionKey]; + } + const item = queriedState.items[context]?.[revisionKey]; + if (item && query._fields) { + var _getNormalizedCommaSe2; + const filteredItem = {}; + const fields = (_getNormalizedCommaSe2 = get_normalized_comma_separable(query._fields)) !== null && _getNormalizedCommaSe2 !== void 0 ? _getNormalizedCommaSe2 : []; + for (let f = 0; f < fields.length; f++) { + const field = fields[f].split('.'); + let value = item; + field.forEach(fieldName => { + value = value?.[fieldName]; + }); + setNestedValue(filteredItem, field, value); + } + return filteredItem; + } + return item; +}, (state, kind, name, recordKey, revisionKey, query) => { + var _query$context6; + const context = (_query$context6 = query?.context) !== null && _query$context6 !== void 0 ? _query$context6 : 'default'; + return [state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]?.items?.[context]?.[revisionKey], state.entities.records?.[kind]?.[name]?.revisions?.[recordKey]?.itemIsComplete?.[context]?.[revisionKey]]; +}); + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/private-selectors.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + +/** + * Returns the previous edit from the current undo offset + * for the entity records edits history, if any. + * + * @param state State tree. + * + * @return The undo manager. + */ +function getUndoManager(state) { + return state.undoManager; +} + +/** + * Retrieve the fallback Navigation. + * + * @param state Data state. + * @return The ID for the fallback Navigation post. + */ +function getNavigationFallbackId(state) { + return state.navigationFallbackId; +} +const getBlockPatternsForPostType = (0,external_wp_data_namespaceObject.createRegistrySelector)(select => (0,external_wp_data_namespaceObject.createSelector)((state, postType) => select(STORE_NAME).getBlockPatterns().filter(({ + postTypes +}) => !postTypes || Array.isArray(postTypes) && postTypes.includes(postType)), () => [select(STORE_NAME).getBlockPatterns()])); + +;// CONCATENATED MODULE: ./node_modules/camel-case/dist.es2015/index.js + + +function camelCaseTransform(input, index) { + if (index === 0) + return input.toLowerCase(); + return pascalCaseTransform(input, index); +} +function camelCaseTransformMerge(input, index) { + if (index === 0) + return input.toLowerCase(); + return pascalCaseTransformMerge(input); +} +function camelCase(input, options) { + if (options === void 0) { options = {}; } + return pascalCase(input, __assign({ transform: camelCaseTransform }, options)); +} + +;// CONCATENATED MODULE: external ["wp","htmlEntities"] +const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"]; ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/utils/forward-resolver.js /** * Higher-order function which forward the resolution to another resolver with the same arguments. @@ -4693,1321 +5472,13 @@ * * @return {Function} Enhanced resolver. */ -const forwardResolver = resolverName => function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - return async _ref => { - let { - resolveSelect - } = _ref; - await resolveSelect[resolverName](...args); - }; -}; - -/* harmony default export */ var forward_resolver = (forwardResolver); - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/resolvers.js -/** - * External dependencies - */ - -/** - * WordPress dependencies - */ - - - -/** - * Internal dependencies - */ - - - - -/** - * Requests authors from the REST API. - * - * @param {Object|undefined} query Optional object of query parameters to - * include with request. - */ - -const resolvers_getAuthors = query => async _ref => { - let { - dispatch - } = _ref; - const path = (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/users/?who=authors&per_page=100', query); - const users = await external_wp_apiFetch_default()({ - path - }); - dispatch.receiveUserQuery(path, users); -}; -/** - * Requests the current user from the REST API. - */ - -const resolvers_getCurrentUser = () => async _ref2 => { - let { - dispatch - } = _ref2; - const currentUser = await external_wp_apiFetch_default()({ - path: '/wp/v2/users/me' - }); - dispatch.receiveCurrentUser(currentUser); -}; -/** - * Requests an entity's record from the REST API. - * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {number|string} key Record's key - * @param {Object|undefined} query Optional object of query parameters to - * include with request. - */ - -const resolvers_getEntityRecord = function (kind, name) { - let key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; - let query = arguments.length > 3 ? arguments[3] : undefined; - return async _ref3 => { - let { - select, - dispatch - } = _ref3; - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { - kind, - name - }); - - if (!entityConfig || entityConfig !== null && entityConfig !== void 0 && entityConfig.__experimentalNoFetch) { - return; - } - - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, key], { - exclusive: false - }); - - try { - if (query !== undefined && query._fields) { - // If requesting specific fields, items and query association to said - // records are stored by ID reference. Thus, fields must always include - // the ID. - query = { ...query, - _fields: (0,external_lodash_namespaceObject.uniq)([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY]).join() - }; - } // Disable reason: While true that an early return could leave `path` - // unused, it's important that path is derived using the query prior to - // additional query modifications in the condition below, since those - // modifications are relevant to how the data is tracked in state, and not - // for how the request is made to the REST API. - // eslint-disable-next-line @wordpress/no-unused-vars-before-return - - - const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL + (key ? '/' + key : ''), { ...entityConfig.baseURLParams, - ...query - }); - - if (query !== undefined) { - query = { ...query, - include: [key] - }; // The resolution cache won't consider query as reusable based on the - // fields, so it's tested here, prior to initiating the REST request, - // and without causing `getEntityRecords` resolution to occur. - - const hasRecords = select.hasEntityRecords(kind, name, query); - - if (hasRecords) { - return; - } - } - - const record = await external_wp_apiFetch_default()({ - path - }); - dispatch.receiveEntityRecords(kind, name, record, query); - } finally { - dispatch.__unstableReleaseStoreLock(lock); - } - }; -}; -/** - * Requests an entity's record from the REST API. - */ - -const resolvers_getRawEntityRecord = forward_resolver('getEntityRecord'); -/** - * Requests an entity's record from the REST API. - */ - -const resolvers_getEditedEntityRecord = forward_resolver('getEntityRecord'); -/** - * Requests the entity's records from the REST API. - * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {Object?} query Query Object. - */ - -const resolvers_getEntityRecords = function (kind, name) { - let query = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - return async _ref4 => { - let { - dispatch - } = _ref4; - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { - kind, - name - }); - - if (!entityConfig || entityConfig !== null && entityConfig !== void 0 && entityConfig.__experimentalNoFetch) { - return; - } - - const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name], { - exclusive: false - }); - - try { - var _query; - - if (query._fields) { - // If requesting specific fields, items and query association to said - // records are stored by ID reference. Thus, fields must always include - // the ID. - query = { ...query, - _fields: (0,external_lodash_namespaceObject.uniq)([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY]).join() - }; - } - - const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL, { ...entityConfig.baseURLParams, - ...query - }); - let records = Object.values(await external_wp_apiFetch_default()({ - path - })); // If we request fields but the result doesn't contain the fields, - // explicitely set these fields as "undefined" - // that way we consider the query "fullfilled". - - if (query._fields) { - records = records.map(record => { - query._fields.split(',').forEach(field => { - if (!record.hasOwnProperty(field)) { - record[field] = undefined; - } - }); - - return record; - }); - } - - dispatch.receiveEntityRecords(kind, name, records, query); // When requesting all fields, the list of results can be used to - // resolve the `getEntityRecord` selector in addition to `getEntityRecords`. - // See https://github.com/WordPress/gutenberg/pull/26575 - - if (!((_query = query) !== null && _query !== void 0 && _query._fields) && !query.context) { - const key = entityConfig.key || DEFAULT_ENTITY_KEY; - const resolutionsArgs = records.filter(record => record[key]).map(record => [kind, name, record[key]]); - dispatch({ - type: 'START_RESOLUTIONS', - selectorName: 'getEntityRecord', - args: resolutionsArgs - }); - dispatch({ - type: 'FINISH_RESOLUTIONS', - selectorName: 'getEntityRecord', - args: resolutionsArgs - }); - } - } finally { - dispatch.__unstableReleaseStoreLock(lock); - } - }; -}; - -resolvers_getEntityRecords.shouldInvalidate = (action, kind, name) => { - return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && kind === action.kind && name === action.name; -}; -/** - * Requests the current theme. - */ - - -const resolvers_getCurrentTheme = () => async _ref5 => { - let { - dispatch, - resolveSelect - } = _ref5; - const activeThemes = await resolveSelect.getEntityRecords('root', 'theme', { - status: 'active' - }); - dispatch.receiveCurrentTheme(activeThemes[0]); -}; -/** - * Requests theme supports data from the index. - */ - -const resolvers_getThemeSupports = forward_resolver('getCurrentTheme'); -/** - * Requests a preview from the from the Embed API. - * - * @param {string} url URL to get the preview for. - */ - -const resolvers_getEmbedPreview = url => async _ref6 => { - let { - dispatch - } = _ref6; - - try { - const embedProxyResponse = await external_wp_apiFetch_default()({ - path: (0,external_wp_url_namespaceObject.addQueryArgs)('/oembed/1.0/proxy', { - url - }) - }); - dispatch.receiveEmbedPreview(url, embedProxyResponse); - } catch (error) { - // Embed API 404s if the URL cannot be embedded, so we have to catch the error from the apiRequest here. - dispatch.receiveEmbedPreview(url, false); - } -}; -/** - * Checks whether the current user can perform the given action on the given - * REST resource. - * - * @param {string} action Action to check. One of: 'create', 'read', 'update', - * 'delete'. - * @param {string} resource REST resource to check, e.g. 'media' or 'posts'. - * @param {?string} id ID of the rest resource to check. - */ - -const resolvers_canUser = (action, resource, id) => async _ref7 => { - var _response$headers; - - let { - dispatch - } = _ref7; - const methods = { - create: 'POST', - read: 'GET', - update: 'PUT', - delete: 'DELETE' - }; - const method = methods[action]; - - if (!method) { - throw new Error(`'${action}' is not a valid action.`); - } - - const path = id ? `/wp/v2/${resource}/${id}` : `/wp/v2/${resource}`; - let response; - - try { - response = await external_wp_apiFetch_default()({ - path, - method: 'OPTIONS', - parse: false - }); - } catch (error) { - // Do nothing if our OPTIONS request comes back with an API error (4xx or - // 5xx). The previously determined isAllowed value will remain in the store. - return; - } // Optional chaining operator is used here because the API requests don't - // return the expected result in the native version. Instead, API requests - // only return the result, without including response properties like the headers. - - - const allowHeader = (_response$headers = response.headers) === null || _response$headers === void 0 ? void 0 : _response$headers.get('allow'); - const key = (0,external_lodash_namespaceObject.compact)([action, resource, id]).join('/'); - const isAllowed = (0,external_lodash_namespaceObject.includes)(allowHeader, method); - dispatch.receiveUserPermission(key, isAllowed); -}; -/** - * Checks whether the current user can perform the given action on the given - * REST resource. - * - * @param {string} kind Entity kind. - * @param {string} name Entity name. - * @param {string} recordId Record's id. - */ - -const resolvers_canUserEditEntityRecord = (kind, name, recordId) => async _ref8 => { - let { - dispatch - } = _ref8; - const configs = await dispatch(getOrLoadEntitiesConfig(kind)); - const entityConfig = (0,external_lodash_namespaceObject.find)(configs, { - kind, - name - }); - - if (!entityConfig) { - return; - } - - const resource = entityConfig.__unstable_rest_base; - await dispatch(resolvers_canUser('update', resource, recordId)); -}; -/** - * Request autosave data from the REST API. - * - * @param {string} postType The type of the parent post. - * @param {number} postId The id of the parent post. - */ - -const resolvers_getAutosaves = (postType, postId) => async _ref9 => { - let { - dispatch, - resolveSelect - } = _ref9; - const { - rest_base: restBase - } = await resolveSelect.getPostType(postType); - const autosaves = await external_wp_apiFetch_default()({ - path: `/wp/v2/${restBase}/${postId}/autosaves?context=edit` - }); - - if (autosaves && autosaves.length) { - dispatch.receiveAutosaves(postId, autosaves); - } -}; -/** - * Request autosave data from the REST API. - * - * This resolver exists to ensure the underlying autosaves are fetched via - * `getAutosaves` when a call to the `getAutosave` selector is made. - * - * @param {string} postType The type of the parent post. - * @param {number} postId The id of the parent post. - */ - -const resolvers_getAutosave = (postType, postId) => async _ref10 => { - let { - resolveSelect - } = _ref10; - await resolveSelect.getAutosaves(postType, postId); -}; -/** - * Retrieve the frontend template used for a given link. - * - * @param {string} link Link. - */ - -const resolvers_experimentalGetTemplateForLink = link => async _ref11 => { - let { - dispatch, - resolveSelect - } = _ref11; - // Ideally this should be using an apiFetch call - // We could potentially do so by adding a "filter" to the `wp_template` end point. - // Also it seems the returned object is not a regular REST API post type. - let template; - - try { - template = await window.fetch((0,external_wp_url_namespaceObject.addQueryArgs)(link, { - '_wp-find-template': true - })).then(res => res.json()).then(_ref12 => { - let { - data - } = _ref12; - return data; - }); - } catch (e) {// For non-FSE themes, it is possible that this request returns an error. - } - - if (!template) { - return; - } - - const record = await resolveSelect.getEntityRecord('postType', 'wp_template', template.id); - - if (record) { - dispatch.receiveEntityRecords('postType', 'wp_template', [record], { - 'find-template': link - }); - } -}; - -resolvers_experimentalGetTemplateForLink.shouldInvalidate = action => { - return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && action.kind === 'postType' && action.name === 'wp_template'; -}; - -const resolvers_experimentalGetCurrentGlobalStylesId = () => async _ref13 => { - let { - dispatch, - resolveSelect - } = _ref13; - const activeThemes = await resolveSelect.getEntityRecords('root', 'theme', { - status: 'active' - }); - const globalStylesURL = (0,external_lodash_namespaceObject.get)(activeThemes, [0, '_links', 'wp:user-global-styles', 0, 'href']); - - if (globalStylesURL) { - const globalStylesObject = await external_wp_apiFetch_default()({ - url: globalStylesURL - }); - - dispatch.__experimentalReceiveCurrentGlobalStylesId(globalStylesObject.id); - } -}; -const resolvers_experimentalGetCurrentThemeBaseGlobalStyles = () => async _ref14 => { - let { - resolveSelect, - dispatch - } = _ref14; - const currentTheme = await resolveSelect.getCurrentTheme(); - const themeGlobalStyles = await external_wp_apiFetch_default()({ - path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}` - }); - - dispatch.__experimentalReceiveThemeBaseGlobalStyles(currentTheme.stylesheet, themeGlobalStyles); -}; -const resolvers_experimentalGetCurrentThemeGlobalStylesVariations = () => async _ref15 => { - let { - resolveSelect, - dispatch - } = _ref15; - const currentTheme = await resolveSelect.getCurrentTheme(); - const variations = await external_wp_apiFetch_default()({ - path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}/variations` - }); - - dispatch.__experimentalReceiveThemeGlobalStyleVariations(currentTheme.stylesheet, variations); -}; -const resolvers_getBlockPatterns = () => async _ref16 => { - let { - dispatch - } = _ref16; - const restPatterns = await external_wp_apiFetch_default()({ - path: '/wp/v2/block-patterns/patterns' - }); - const patterns = (0,external_lodash_namespaceObject.map)(restPatterns, pattern => (0,external_lodash_namespaceObject.mapKeys)(pattern, (value, key) => { - switch (key) { - case 'block_types': - return 'blockTypes'; - - case 'viewport_width': - return 'viewportWidth'; - - default: - return key; - } - })); - dispatch({ - type: 'RECEIVE_BLOCK_PATTERNS', - patterns - }); -}; -const resolvers_getBlockPatternCategories = () => async _ref17 => { - let { - dispatch - } = _ref17; - const categories = await external_wp_apiFetch_default()({ - path: '/wp/v2/block-patterns/categories' - }); - dispatch({ - type: 'RECEIVE_BLOCK_PATTERN_CATEGORIES', - categories - }); -}; - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/utils.js -function deepCopyLocksTreePath(tree, path) { - const newTree = { ...tree - }; - let currentNode = newTree; - - for (const branchName of path) { - currentNode.children = { ...currentNode.children, - [branchName]: { - locks: [], - children: {}, - ...currentNode.children[branchName] - } - }; - currentNode = currentNode.children[branchName]; - } - - return newTree; -} -function getNode(tree, path) { - let currentNode = tree; - - for (const branchName of path) { - const nextNode = currentNode.children[branchName]; - - if (!nextNode) { - return null; - } - - currentNode = nextNode; - } - - return currentNode; -} -function* iteratePath(tree, path) { - let currentNode = tree; - yield currentNode; - - for (const branchName of path) { - const nextNode = currentNode.children[branchName]; - - if (!nextNode) { - break; - } - - yield nextNode; - currentNode = nextNode; - } -} -function* iterateDescendants(node) { - const stack = Object.values(node.children); - - while (stack.length) { - const childNode = stack.pop(); - yield childNode; - stack.push(...Object.values(childNode.children)); - } -} -function hasConflictingLock(_ref, locks) { - let { - exclusive - } = _ref; - - if (exclusive && locks.length) { - return true; - } - - if (!exclusive && locks.filter(lock => lock.exclusive).length) { - return true; - } - - return false; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/reducer.js -/** - * Internal dependencies - */ - -const DEFAULT_STATE = { - requests: [], - tree: { - locks: [], - children: {} - } +const forwardResolver = resolverName => (...args) => async ({ + resolveSelect +}) => { + await resolveSelect[resolverName](...args); }; -/** - * Reducer returning locks. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {Object} Updated state. - */ - -function locks() { - let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_STATE; - let action = arguments.length > 1 ? arguments[1] : undefined; - - switch (action.type) { - case 'ENQUEUE_LOCK_REQUEST': - { - const { - request - } = action; - return { ...state, - requests: [request, ...state.requests] - }; - } - - case 'GRANT_LOCK_REQUEST': - { - const { - lock, - request - } = action; - const { - store, - path - } = request; - const storePath = [store, ...path]; - const newTree = deepCopyLocksTreePath(state.tree, storePath); - const node = getNode(newTree, storePath); - node.locks = [...node.locks, lock]; - return { ...state, - requests: state.requests.filter(r => r !== request), - tree: newTree - }; - } - - case 'RELEASE_LOCK': - { - const { - lock - } = action; - const storePath = [lock.store, ...lock.path]; - const newTree = deepCopyLocksTreePath(state.tree, storePath); - const node = getNode(newTree, storePath); - node.locks = node.locks.filter(l => l !== lock); - return { ...state, - tree: newTree - }; - } - } - - return state; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/selectors.js -/** - * Internal dependencies - */ - -function getPendingLockRequests(state) { - return state.requests; -} -function isLockAvailable(state, store, path, _ref) { - let { - exclusive - } = _ref; - const storePath = [store, ...path]; - const locks = state.tree; // Validate all parents and the node itself - - for (const node of iteratePath(locks, storePath)) { - if (hasConflictingLock({ - exclusive - }, node.locks)) { - return false; - } - } // iteratePath terminates early if path is unreachable, let's - // re-fetch the node and check it exists in the tree. - - - const node = getNode(locks, storePath); - - if (!node) { - return true; - } // Validate all nested nodes - - - for (const descendant of iterateDescendants(node)) { - if (hasConflictingLock({ - exclusive - }, descendant.locks)) { - return false; - } - } - - return true; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/engine.js -/** - * Internal dependencies - */ - - -function createLocks() { - let state = locks(undefined, { - type: '@@INIT' - }); - - function processPendingLockRequests() { - for (const request of getPendingLockRequests(state)) { - const { - store, - path, - exclusive, - notifyAcquired - } = request; - - if (isLockAvailable(state, store, path, { - exclusive - })) { - const lock = { - store, - path, - exclusive - }; - state = locks(state, { - type: 'GRANT_LOCK_REQUEST', - lock, - request - }); - notifyAcquired(lock); - } - } - } - - function acquire(store, path, exclusive) { - return new Promise(resolve => { - state = locks(state, { - type: 'ENQUEUE_LOCK_REQUEST', - request: { - store, - path, - exclusive, - notifyAcquired: resolve - } - }); - processPendingLockRequests(); - }); - } - - function release(lock) { - state = locks(state, { - type: 'RELEASE_LOCK', - lock - }); - processPendingLockRequests(); - } - - return { - acquire, - release - }; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/actions.js -/** - * Internal dependencies - */ - -function createLocksActions() { - const locks = createLocks(); - - function __unstableAcquireStoreLock(store, path, _ref) { - let { - exclusive - } = _ref; - return () => locks.acquire(store, path, exclusive); - } - - function __unstableReleaseStoreLock(lock) { - return () => locks.release(lock); - } - - return { - __unstableAcquireStoreLock, - __unstableReleaseStoreLock - }; -} - -;// CONCATENATED MODULE: external ["wp","element"] -var external_wp_element_namespaceObject = window["wp"]["element"]; -;// CONCATENATED MODULE: external ["wp","blocks"] -var external_wp_blocks_namespaceObject = window["wp"]["blocks"]; -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/entity-provider.js - - -/** - * WordPress dependencies - */ - - - -/** - * Internal dependencies - */ - - -/** @typedef {import('@wordpress/blocks').WPBlock} WPBlock */ - -const EMPTY_ARRAY = []; -/** - * Internal dependencies - */ - - -const entityContexts = { ...rootEntitiesConfig.reduce((acc, loader) => { - if (!acc[loader.kind]) { - acc[loader.kind] = {}; - } - - acc[loader.kind][loader.name] = { - context: (0,external_wp_element_namespaceObject.createContext)(undefined) - }; - return acc; - }, {}), - ...additionalEntityConfigLoaders.reduce((acc, loader) => { - acc[loader.kind] = {}; - return acc; - }, {}) -}; - -const getEntityContext = (kind, name) => { - if (!entityContexts[kind]) { - throw new Error(`Missing entity config for kind: ${kind}.`); - } - - if (!entityContexts[kind][name]) { - entityContexts[kind][name] = { - context: (0,external_wp_element_namespaceObject.createContext)(undefined) - }; - } - - return entityContexts[kind][name].context; -}; -/** - * Context provider component for providing - * an entity for a specific entity. - * - * @param {Object} props The component's props. - * @param {string} props.kind The entity kind. - * @param {string} props.type The entity name. - * @param {number} props.id The entity ID. - * @param {*} props.children The children to wrap. - * - * @return {Object} The provided children, wrapped with - * the entity's context provider. - */ - - -function EntityProvider(_ref) { - let { - kind, - type: name, - id, - children - } = _ref; - const Provider = getEntityContext(kind, name).Provider; - return (0,external_wp_element_namespaceObject.createElement)(Provider, { - value: id - }, children); -} -/** - * Hook that returns the ID for the nearest - * provided entity of the specified type. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - */ - -function useEntityId(kind, name) { - return (0,external_wp_element_namespaceObject.useContext)(getEntityContext(kind, name)); -} -/** - * Hook that returns the value and a setter for the - * specified property of the nearest provided - * entity of the specified type. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - * @param {string} prop The property name. - * @param {string} [_id] An entity ID to use instead of the context-provided one. - * - * @return {[*, Function, *]} An array where the first item is the - * property value, the second is the - * setter and the third is the full value - * object from REST API containing more - * information like `raw`, `rendered` and - * `protected` props. - */ - -function useEntityProp(kind, name, prop, _id) { - const providerId = useEntityId(kind, name); - const id = _id !== null && _id !== void 0 ? _id : providerId; - const { - value, - fullValue - } = (0,external_wp_data_namespaceObject.useSelect)(select => { - const { - getEntityRecord, - getEditedEntityRecord - } = select(STORE_NAME); - const record = getEntityRecord(kind, name, id); // Trigger resolver. - - const editedRecord = getEditedEntityRecord(kind, name, id); - return record && editedRecord ? { - value: editedRecord[prop], - fullValue: record[prop] - } : {}; - }, [kind, name, id, prop]); - const { - editEntityRecord - } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); - const setValue = (0,external_wp_element_namespaceObject.useCallback)(newValue => { - editEntityRecord(kind, name, id, { - [prop]: newValue - }); - }, [kind, name, id, prop]); - return [value, setValue, fullValue]; -} -/** - * Hook that returns block content getters and setters for - * the nearest provided entity of the specified type. - * - * The return value has the shape `[ blocks, onInput, onChange ]`. - * `onInput` is for block changes that don't create undo levels - * or dirty the post, non-persistent changes, and `onChange` is for - * peristent changes. They map directly to the props of a - * `BlockEditorProvider` and are intended to be used with it, - * or similar components or hooks. - * - * @param {string} kind The entity kind. - * @param {string} name The entity name. - * @param {Object} options - * @param {string} [options.id] An entity ID to use instead of the context-provided one. - * - * @return {[WPBlock[], Function, Function]} The block array and setters. - */ - -function useEntityBlockEditor(kind, name) { - let { - id: _id - } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - const providerId = useEntityId(kind, name); - const id = _id !== null && _id !== void 0 ? _id : providerId; - const { - content, - blocks - } = (0,external_wp_data_namespaceObject.useSelect)(select => { - const { - getEditedEntityRecord - } = select(STORE_NAME); - const editedRecord = getEditedEntityRecord(kind, name, id); - return { - blocks: editedRecord.blocks, - content: editedRecord.content - }; - }, [kind, name, id]); - const { - __unstableCreateUndoLevel, - editEntityRecord - } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); - (0,external_wp_element_namespaceObject.useEffect)(() => { - // Load the blocks from the content if not already in state - // Guard against other instances that might have - // set content to a function already or the blocks are already in state. - if (content && typeof content !== 'function' && !blocks) { - const parsedContent = (0,external_wp_blocks_namespaceObject.parse)(content); - editEntityRecord(kind, name, id, { - blocks: parsedContent - }, { - undoIgnore: true - }); - } - }, [content]); - const onChange = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { - const { - selection - } = options; - const edits = { - blocks: newBlocks, - selection - }; - const noChange = blocks === edits.blocks; - - if (noChange) { - return __unstableCreateUndoLevel(kind, name, id); - } // We create a new function here on every persistent edit - // to make sure the edit makes the post dirty and creates - // a new undo level. - - - edits.content = _ref2 => { - let { - blocks: blocksForSerialization = [] - } = _ref2; - return (0,external_wp_blocks_namespaceObject.__unstableSerializeAndClean)(blocksForSerialization); - }; - - editEntityRecord(kind, name, id, edits); - }, [kind, name, id, blocks]); - const onInput = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { - const { - selection - } = options; - const edits = { - blocks: newBlocks, - selection - }; - editEntityRecord(kind, name, id, edits); - }, [kind, name, id]); - return [blocks !== null && blocks !== void 0 ? blocks : EMPTY_ARRAY, onInput, onChange]; -} - -// EXTERNAL MODULE: ./node_modules/memize/index.js -var memize = __webpack_require__(9756); -var memize_default = /*#__PURE__*/__webpack_require__.n(memize); -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/memoize.js -/** - * External dependencies - */ - // re-export due to restrictive esModuleInterop setting - -/* harmony default export */ var memoize = ((memize_default())); - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/constants.js -/* eslint-disable-next-line no-shadow */ -let Status; - -(function (Status) { - Status["Idle"] = "IDLE"; - Status["Resolving"] = "RESOLVING"; - Status["Error"] = "ERROR"; - Status["Success"] = "SUCCESS"; -})(Status || (Status = {})); - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-query-select.js -/** - * WordPress dependencies - */ - -/** - * Internal dependencies - */ - - - -const META_SELECTORS = ['getIsResolving', 'hasStartedResolution', 'hasFinishedResolution', 'isResolving', 'getCachedResolvers']; - -/** - * Like useSelect, but the selectors return objects containing - * both the original data AND the resolution info. - * - * @param {Function} mapQuerySelect see useSelect - * @param {Array} deps see useSelect - * - * @example - * ```js - * import { useQuerySelect } from '@wordpress/data'; - * import { store as coreDataStore } from '@wordpress/core-data'; - * - * function PageTitleDisplay( { id } ) { - * const { data: page, isResolving } = useQuerySelect( ( query ) => { - * return query( coreDataStore ).getEntityRecord( 'postType', 'page', id ) - * }, [ id ] ); - * - * if ( isResolving ) { - * return 'Loading...'; - * } - * - * return page.title; - * } - * - * // Rendered in the application: - * // - * ``` - * - * In the above example, when `PageTitleDisplay` is rendered into an - * application, the page and the resolution details will be retrieved from - * the store state using the `mapSelect` callback on `useQuerySelect`. - * - * If the id prop changes then any page in the state for that id is - * retrieved. If the id prop doesn't change and other props are passed in - * that do change, the title will not change because the dependency is just - * the id. - * @see useSelect - * - * @return {QuerySelectResponse} Queried data. - */ -function __experimentalUseQuerySelect(mapQuerySelect, deps) { - return (0,external_wp_data_namespaceObject.useSelect)((select, registry) => { - const resolve = store => enrichSelectors(select(store)); - - return mapQuerySelect(resolve, registry); - }, deps); -} - -/** - * Transform simple selectors into ones that return an object with the - * original return value AND the resolution info. - * - * @param {Object} selectors Selectors to enrich - * @return {EnrichedSelectors} Enriched selectors - */ -const enrichSelectors = memoize(selectors => { - const resolvers = {}; - - for (const selectorName in selectors) { - if (META_SELECTORS.includes(selectorName)) { - continue; - } - - Object.defineProperty(resolvers, selectorName, { - get: () => function () { - const { - getIsResolving, - hasFinishedResolution - } = selectors; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - const isResolving = !!getIsResolving(selectorName, args); - const hasResolved = !isResolving && hasFinishedResolution(selectorName, args); - const data = selectors[selectorName](...args); - let status; - - if (isResolving) { - status = Status.Resolving; - } else if (hasResolved) { - if (data) { - status = Status.Success; - } else { - status = Status.Error; - } - } else { - status = Status.Idle; - } - - return { - data, - status, - isResolving, - hasResolved - }; - } - }); - } - - return resolvers; -}); - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-record.js -/** - * Internal dependencies - */ - - - -/** - * Resolves the specified entity record. - * - * @param kind Kind of the requested entity. - * @param name Name of the requested entity. - * @param recordId Record ID of the requested entity. - * @param options Hook options. - * @param [options.enabled=true] Whether to run the query or short-circuit and return null. Defaults to true. - * @example - * ```js - * import { useEntityRecord } from '@wordpress/core-data'; - * - * function PageTitleDisplay( { id } ) { - * const { record, isResolving } = useEntityRecord( 'postType', 'page', id ); - * - * if ( isResolving ) { - * return 'Loading...'; - * } - * - * return record.title; - * } - * - * // Rendered in the application: - * // - * ``` - * - * In the above example, when `PageTitleDisplay` is rendered into an - * application, the page and the resolution details will be retrieved from - * the store state using `getEntityRecord()`, or resolved if missing. - * - * @return {EntityRecordResolution} Entity record data. - * @template RecordType - */ -function __experimentalUseEntityRecord(kind, name, recordId) { - let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { - enabled: true - }; - const { - data: record, - ...rest - } = __experimentalUseQuerySelect(query => { - if (!options.enabled) { - return null; - } - - return query(store).getEntityRecord(kind, name, recordId); - }, [kind, name, recordId, options.enabled]); - return { - record, - ...rest - }; -} - -;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-records.js -/** - * WordPress dependencies - */ - -/** - * Internal dependencies - */ - - - - -/** - * Resolves the specified entity records. - * - * @param kind Kind of the requested entities. - * @param name Name of the requested entities. - * @param queryArgs HTTP query for the requested entities. - * @param options Hook options. - * @example - * ```js - * import { useEntityRecord } from '@wordpress/core-data'; - * - * function PageTitlesList() { - * const { records, isResolving } = useEntityRecords( 'postType', 'page' ); - * - * if ( isResolving ) { - * return 'Loading...'; - * } - * - * return ( - *
    - * {records.map(( page ) => ( - *
  • { page.title }
  • - * ))} - *
- * ); - * } - * - * // Rendered in the application: - * // - * ``` - * - * In the above example, when `PageTitlesList` is rendered into an - * application, the list of records and the resolution details will be retrieved from - * the store state using `getEntityRecords()`, or resolved if missing. - * - * @return Entity records data. - * @template RecordType - */ -function __experimentalUseEntityRecords(kind, name) { - let queryArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { - enabled: true - }; - // Serialize queryArgs to a string that can be safely used as a React dep. - // We can't just pass queryArgs as one of the deps, because if it is passed - // as an object literal, then it will be a different object on each call even - // if the values remain the same. - const queryAsString = (0,external_wp_url_namespaceObject.addQueryArgs)('', queryArgs); - const { - data: records, - ...rest - } = __experimentalUseQuerySelect(query => { - if (!options.enabled) { - return { - data: [] - }; - } - - return query(store).getEntityRecords(kind, name, queryArgs); - }, [kind, name, queryAsString, options.enabled]); - return { - records, - ...rest - }; -} - -;// CONCATENATED MODULE: external ["wp","htmlEntities"] -var external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"]; +/* harmony default export */ const forward_resolver = (forwardResolver); + ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-link-suggestions.js /** * WordPress dependencies @@ -6016,6 +5487,7 @@ + /** * Filters the search by type * @@ -6088,24 +5560,29 @@ * ``` * @return {Promise< WPLinkSearchResult[] >} List of search suggestions */ - -const fetchLinkSuggestions = async function (search) { - let searchOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let settings = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; +const fetchLinkSuggestions = async (search, searchOptions = {}, settings = {}) => { const { isInitialSuggestions = false, + initialSuggestionsSearchOptions = undefined + } = searchOptions; + const { + disablePostFormats = false + } = settings; + let { type = undefined, subtype = undefined, page = undefined, perPage = isInitialSuggestions ? 3 : 20 } = searchOptions; - const { - disablePostFormats = false - } = settings; + /** @type {Promise[]} */ - const queries = []; - + if (isInitialSuggestions && initialSuggestionsSearchOptions) { + type = initialSuggestionsSearchOptions.type || type; + subtype = initialSuggestionsSearchOptions.subtype || subtype; + page = initialSuggestionsSearchOptions.page || page; + perPage = initialSuggestionsSearchOptions.perPage || perPage; + } if (!type || type === 'post') { queries.push(external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', { @@ -6117,7 +5594,8 @@ }) }).then(results => { return results.map(result => { - return { ...result, + return { + ...result, meta: { kind: 'post-type', subtype @@ -6127,7 +5605,6 @@ }).catch(() => []) // Fail by returning no results. ); } - if (!type || type === 'term') { queries.push(external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', { @@ -6139,7 +5616,8 @@ }) }).then(results => { return results.map(result => { - return { ...result, + return { + ...result, meta: { kind: 'taxonomy', subtype @@ -6149,7 +5627,6 @@ }).catch(() => []) // Fail by returning no results. ); } - if (!disablePostFormats && (!type || type === 'post-format')) { queries.push(external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/search', { @@ -6161,7 +5638,8 @@ }) }).then(results => { return results.map(result => { - return { ...result, + return { + ...result, meta: { kind: 'taxonomy', subtype @@ -6171,7 +5649,6 @@ }).catch(() => []) // Fail by returning no results. ); } - if (!type || type === 'attachment') { queries.push(external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/media', { @@ -6181,7 +5658,8 @@ }) }).then(results => { return results.map(result => { - return { ...result, + return { + ...result, meta: { kind: 'media' } @@ -6190,37 +5668,31 @@ }).catch(() => []) // Fail by returning no results. ); } - return Promise.all(queries).then(results => { - return results.reduce(( - /** @type {WPLinkSearchResult[]} */ - accumulator, current) => accumulator.concat(current), // Flatten list. + return results.reduce(( /** @type {WPLinkSearchResult[]} */accumulator, current) => accumulator.concat(current), + // Flatten list. []).filter( /** * @param {{ id: number }} result */ result => { return !!result.id; - }).slice(0, perPage).map(( - /** @type {WPLinkSearchResultAugmented} */ - result) => { - var _result$meta; - + }).slice(0, perPage).map(( /** @type {WPLinkSearchResultAugmented} */result) => { const isMedia = result.type === 'attachment'; return { id: result.id, // @ts-ignore fix when we make this a TS file url: isMedia ? result.source_url : result.url, - title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(isMedia ? // @ts-ignore fix when we make this a TS file + title: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(isMedia ? + // @ts-ignore fix when we make this a TS file result.title.rendered : result.title || '') || (0,external_wp_i18n_namespaceObject.__)('(no title)'), type: result.subtype || result.type, - kind: result === null || result === void 0 ? void 0 : (_result$meta = result.meta) === null || _result$meta === void 0 ? void 0 : _result$meta.kind + kind: result?.meta?.kind }; }); }); }; - -/* harmony default export */ var _experimental_fetch_link_suggestions = (fetchLinkSuggestions); +/* harmony default export */ const _experimental_fetch_link_suggestions = (fetchLinkSuggestions); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/__experimental-fetch-url-data.js /** @@ -6228,13 +5700,14 @@ */ + /** * A simple in-memory cache for requests. * This avoids repeat HTTP requests which may be beneficial * for those wishing to preserve low-bandwidth. */ - const CACHE = new Map(); + /** * @typedef WPRemoteUrlData * @@ -6262,30 +5735,24 @@ * ``` * @return {Promise< WPRemoteUrlData[] >} Remote URL data. */ - -const fetchUrlData = async function (url) { - let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; +const fetchUrlData = async (url, options = {}) => { const endpoint = '/wp-block-editor/v1/url-details'; const args = { url: (0,external_wp_url_namespaceObject.prependHTTP)(url) }; - if (!(0,external_wp_url_namespaceObject.isURL)(url)) { return Promise.reject(`${url} is not a valid URL.`); - } // Test for "http" based URL as it is possible for valid + } + + // Test for "http" based URL as it is possible for valid // yet unusable URLs such as `tel:123456` to be passed. - - const protocol = (0,external_wp_url_namespaceObject.getProtocol)(url); - if (!protocol || !(0,external_wp_url_namespaceObject.isValidProtocol)(protocol) || !protocol.startsWith('http') || !/^https?:\/\/[^\/\s]/i.test(url)) { return Promise.reject(`${url} does not have a valid protocol. URLs must be "http" based`); } - if (CACHE.has(url)) { return CACHE.get(url); } - return external_wp_apiFetch_default()({ path: (0,external_wp_url_namespaceObject.addQueryArgs)(endpoint, args), ...options @@ -6294,10 +5761,2095 @@ return res; }); }; - -/* harmony default export */ var _experimental_fetch_url_data = (fetchUrlData); +/* harmony default export */ const _experimental_fetch_url_data = (fetchUrlData); ;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/fetch/index.js +/** + * External dependencies + */ + + +/** + * WordPress dependencies + */ + + + +async function fetchBlockPatterns() { + const restPatterns = await external_wp_apiFetch_default()({ + path: '/wp/v2/block-patterns/patterns' + }); + if (!restPatterns) { + return []; + } + return restPatterns.map(pattern => Object.fromEntries(Object.entries(pattern).map(([key, value]) => [camelCase(key), value]))); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/resolvers.js +/** + * External dependencies + */ + + +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + + + + + +/** + * Requests authors from the REST API. + * + * @param {Object|undefined} query Optional object of query parameters to + * include with request. + */ +const resolvers_getAuthors = query => async ({ + dispatch +}) => { + const path = (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/users/?who=authors&per_page=100', query); + const users = await external_wp_apiFetch_default()({ + path + }); + dispatch.receiveUserQuery(path, users); +}; + +/** + * Requests the current user from the REST API. + */ +const resolvers_getCurrentUser = () => async ({ + dispatch +}) => { + const currentUser = await external_wp_apiFetch_default()({ + path: '/wp/v2/users/me' + }); + dispatch.receiveCurrentUser(currentUser); +}; + +/** + * Requests an entity's record from the REST API. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} key Record's key + * @param {Object|undefined} query Optional object of query parameters to + * include with request. If requesting specific + * fields, fields must always include the ID. + */ +const resolvers_getEntityRecord = (kind, name, key = '', query) => async ({ + select, + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.name === name && config.kind === kind); + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, key], { + exclusive: false + }); + try { + // Entity supports configs, + // use the sync algorithm instead of the old fetch behavior. + if (window.__experimentalEnableSync && entityConfig.syncConfig && !query) { + if (false) {} + } else { + if (query !== undefined && query._fields) { + // If requesting specific fields, items and query association to said + // records are stored by ID reference. Thus, fields must always include + // the ID. + query = { + ...query, + _fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join() + }; + } + + // Disable reason: While true that an early return could leave `path` + // unused, it's important that path is derived using the query prior to + // additional query modifications in the condition below, since those + // modifications are relevant to how the data is tracked in state, and not + // for how the request is made to the REST API. + + // eslint-disable-next-line @wordpress/no-unused-vars-before-return + const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL + (key ? '/' + key : ''), { + ...entityConfig.baseURLParams, + ...query + }); + if (query !== undefined) { + query = { + ...query, + include: [key] + }; + + // The resolution cache won't consider query as reusable based on the + // fields, so it's tested here, prior to initiating the REST request, + // and without causing `getEntityRecords` resolution to occur. + const hasRecords = select.hasEntityRecords(kind, name, query); + if (hasRecords) { + return; + } + } + const record = await external_wp_apiFetch_default()({ + path + }); + dispatch.receiveEntityRecords(kind, name, record, query); + } + } finally { + dispatch.__unstableReleaseStoreLock(lock); + } +}; + +/** + * Requests an entity's record from the REST API. + */ +const resolvers_getRawEntityRecord = forward_resolver('getEntityRecord'); + +/** + * Requests an entity's record from the REST API. + */ +const resolvers_getEditedEntityRecord = forward_resolver('getEntityRecord'); + +/** + * Requests the entity's records from the REST API. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {Object?} query Query Object. If requesting specific fields, fields + * must always include the ID. + */ +const resolvers_getEntityRecords = (kind, name, query = {}) => async ({ + dispatch, + registry +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.name === name && config.kind === kind); + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name], { + exclusive: false + }); + try { + if (query._fields) { + // If requesting specific fields, items and query association to said + // records are stored by ID reference. Thus, fields must always include + // the ID. + query = { + ...query, + _fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.key || DEFAULT_ENTITY_KEY])].join() + }; + } + const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.baseURL, { + ...entityConfig.baseURLParams, + ...query + }); + let records, meta; + if (entityConfig.supportsPagination && query.per_page !== -1) { + const response = await external_wp_apiFetch_default()({ + path, + parse: false + }); + records = Object.values(await response.json()); + meta = { + totalItems: parseInt(response.headers.get('X-WP-Total')), + totalPages: parseInt(response.headers.get('X-WP-TotalPages')) + }; + } else { + records = Object.values(await external_wp_apiFetch_default()({ + path + })); + } + + // If we request fields but the result doesn't contain the fields, + // explicitly set these fields as "undefined" + // that way we consider the query "fulfilled". + if (query._fields) { + records = records.map(record => { + query._fields.split(',').forEach(field => { + if (!record.hasOwnProperty(field)) { + record[field] = undefined; + } + }); + return record; + }); + } + registry.batch(() => { + dispatch.receiveEntityRecords(kind, name, records, query, false, undefined, meta); + + // When requesting all fields, the list of results can be used to + // resolve the `getEntityRecord` selector in addition to `getEntityRecords`. + // See https://github.com/WordPress/gutenberg/pull/26575 + if (!query?._fields && !query.context) { + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + const resolutionsArgs = records.filter(record => record?.[key]).map(record => [kind, name, record[key]]); + dispatch({ + type: 'START_RESOLUTIONS', + selectorName: 'getEntityRecord', + args: resolutionsArgs + }); + dispatch({ + type: 'FINISH_RESOLUTIONS', + selectorName: 'getEntityRecord', + args: resolutionsArgs + }); + } + dispatch.__unstableReleaseStoreLock(lock); + }); + } catch (e) { + dispatch.__unstableReleaseStoreLock(lock); + } +}; +resolvers_getEntityRecords.shouldInvalidate = (action, kind, name) => { + return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && kind === action.kind && name === action.name; +}; + +/** + * Requests the current theme. + */ +const resolvers_getCurrentTheme = () => async ({ + dispatch, + resolveSelect +}) => { + const activeThemes = await resolveSelect.getEntityRecords('root', 'theme', { + status: 'active' + }); + dispatch.receiveCurrentTheme(activeThemes[0]); +}; + +/** + * Requests theme supports data from the index. + */ +const resolvers_getThemeSupports = forward_resolver('getCurrentTheme'); + +/** + * Requests a preview from the Embed API. + * + * @param {string} url URL to get the preview for. + */ +const resolvers_getEmbedPreview = url => async ({ + dispatch +}) => { + try { + const embedProxyResponse = await external_wp_apiFetch_default()({ + path: (0,external_wp_url_namespaceObject.addQueryArgs)('/oembed/1.0/proxy', { + url + }) + }); + dispatch.receiveEmbedPreview(url, embedProxyResponse); + } catch (error) { + // Embed API 404s if the URL cannot be embedded, so we have to catch the error from the apiRequest here. + dispatch.receiveEmbedPreview(url, false); + } +}; + +/** + * Checks whether the current user can perform the given action on the given + * REST resource. + * + * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update', + * 'delete'. + * @param {string} resource REST resource to check, e.g. 'media' or 'posts'. + * @param {?string} id ID of the rest resource to check. + */ +const resolvers_canUser = (requestedAction, resource, id) => async ({ + dispatch, + registry +}) => { + const { + hasStartedResolution + } = registry.select(STORE_NAME); + const resourcePath = id ? `${resource}/${id}` : resource; + const retrievedActions = ['create', 'read', 'update', 'delete']; + if (!retrievedActions.includes(requestedAction)) { + throw new Error(`'${requestedAction}' is not a valid action.`); + } + + // Prevent resolving the same resource twice. + for (const relatedAction of retrievedActions) { + if (relatedAction === requestedAction) { + continue; + } + const isAlreadyResolving = hasStartedResolution('canUser', [relatedAction, resource, id]); + if (isAlreadyResolving) { + return; + } + } + let response; + try { + response = await external_wp_apiFetch_default()({ + path: `/wp/v2/${resourcePath}`, + method: 'OPTIONS', + parse: false + }); + } catch (error) { + // Do nothing if our OPTIONS request comes back with an API error (4xx or + // 5xx). The previously determined isAllowed value will remain in the store. + return; + } + + // Optional chaining operator is used here because the API requests don't + // return the expected result in the native version. Instead, API requests + // only return the result, without including response properties like the headers. + const allowHeader = response.headers?.get('allow'); + const allowedMethods = allowHeader?.allow || allowHeader || ''; + const permissions = {}; + const methods = { + create: 'POST', + read: 'GET', + update: 'PUT', + delete: 'DELETE' + }; + for (const [actionName, methodName] of Object.entries(methods)) { + permissions[actionName] = allowedMethods.includes(methodName); + } + for (const action of retrievedActions) { + dispatch.receiveUserPermission(`${action}/${resourcePath}`, permissions[action]); + } +}; + +/** + * Checks whether the current user can perform the given action on the given + * REST resource. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {string} recordId Record's id. + */ +const resolvers_canUserEditEntityRecord = (kind, name, recordId) => async ({ + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.name === name && config.kind === kind); + if (!entityConfig) { + return; + } + const resource = entityConfig.__unstable_rest_base; + await dispatch(resolvers_canUser('update', resource, recordId)); +}; + +/** + * Request autosave data from the REST API. + * + * @param {string} postType The type of the parent post. + * @param {number} postId The id of the parent post. + */ +const resolvers_getAutosaves = (postType, postId) => async ({ + dispatch, + resolveSelect +}) => { + const { + rest_base: restBase, + rest_namespace: restNamespace = 'wp/v2' + } = await resolveSelect.getPostType(postType); + const autosaves = await external_wp_apiFetch_default()({ + path: `/${restNamespace}/${restBase}/${postId}/autosaves?context=edit` + }); + if (autosaves && autosaves.length) { + dispatch.receiveAutosaves(postId, autosaves); + } +}; + +/** + * Request autosave data from the REST API. + * + * This resolver exists to ensure the underlying autosaves are fetched via + * `getAutosaves` when a call to the `getAutosave` selector is made. + * + * @param {string} postType The type of the parent post. + * @param {number} postId The id of the parent post. + */ +const resolvers_getAutosave = (postType, postId) => async ({ + resolveSelect +}) => { + await resolveSelect.getAutosaves(postType, postId); +}; + +/** + * Retrieve the frontend template used for a given link. + * + * @param {string} link Link. + */ +const resolvers_experimentalGetTemplateForLink = link => async ({ + dispatch, + resolveSelect +}) => { + let template; + try { + // This is NOT calling a REST endpoint but rather ends up with a response from + // an Ajax function which has a different shape from a WP_REST_Response. + template = await external_wp_apiFetch_default()({ + url: (0,external_wp_url_namespaceObject.addQueryArgs)(link, { + '_wp-find-template': true + }) + }).then(({ + data + }) => data); + } catch (e) { + // For non-FSE themes, it is possible that this request returns an error. + } + if (!template) { + return; + } + const record = await resolveSelect.getEntityRecord('postType', 'wp_template', template.id); + if (record) { + dispatch.receiveEntityRecords('postType', 'wp_template', [record], { + 'find-template': link + }); + } +}; +resolvers_experimentalGetTemplateForLink.shouldInvalidate = action => { + return (action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS') && action.invalidateCache && action.kind === 'postType' && action.name === 'wp_template'; +}; +const resolvers_experimentalGetCurrentGlobalStylesId = () => async ({ + dispatch, + resolveSelect +}) => { + const activeThemes = await resolveSelect.getEntityRecords('root', 'theme', { + status: 'active' + }); + const globalStylesURL = activeThemes?.[0]?._links?.['wp:user-global-styles']?.[0]?.href; + if (!globalStylesURL) { + return; + } + + // Regex matches the ID at the end of a URL or immediately before + // the query string. + const matches = globalStylesURL.match(/\/(\d+)(?:\?|$)/); + const id = matches ? Number(matches[1]) : null; + if (id) { + dispatch.__experimentalReceiveCurrentGlobalStylesId(id); + } +}; +const resolvers_experimentalGetCurrentThemeBaseGlobalStyles = () => async ({ + resolveSelect, + dispatch +}) => { + const currentTheme = await resolveSelect.getCurrentTheme(); + const themeGlobalStyles = await external_wp_apiFetch_default()({ + path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}` + }); + dispatch.__experimentalReceiveThemeBaseGlobalStyles(currentTheme.stylesheet, themeGlobalStyles); +}; +const resolvers_experimentalGetCurrentThemeGlobalStylesVariations = () => async ({ + resolveSelect, + dispatch +}) => { + const currentTheme = await resolveSelect.getCurrentTheme(); + const variations = await external_wp_apiFetch_default()({ + path: `/wp/v2/global-styles/themes/${currentTheme.stylesheet}/variations` + }); + dispatch.__experimentalReceiveThemeGlobalStyleVariations(currentTheme.stylesheet, variations); +}; + +/** + * Fetches and returns the revisions of the current global styles theme. + */ +const resolvers_getCurrentThemeGlobalStylesRevisions = () => async ({ + resolveSelect, + dispatch +}) => { + const globalStylesId = await resolveSelect.__experimentalGetCurrentGlobalStylesId(); + const record = globalStylesId ? await resolveSelect.getEntityRecord('root', 'globalStyles', globalStylesId) : undefined; + const revisionsURL = record?._links?.['version-history']?.[0]?.href; + if (revisionsURL) { + const resetRevisions = await external_wp_apiFetch_default()({ + url: revisionsURL + }); + const revisions = resetRevisions?.map(revision => Object.fromEntries(Object.entries(revision).map(([key, value]) => [camelCase(key), value]))); + dispatch.receiveThemeGlobalStyleRevisions(globalStylesId, revisions); + } +}; +resolvers_getCurrentThemeGlobalStylesRevisions.shouldInvalidate = action => { + return action.type === 'SAVE_ENTITY_RECORD_FINISH' && action.kind === 'root' && !action.error && action.name === 'globalStyles'; +}; +const resolvers_getBlockPatterns = () => async ({ + dispatch +}) => { + const patterns = await fetchBlockPatterns(); + dispatch({ + type: 'RECEIVE_BLOCK_PATTERNS', + patterns + }); +}; +const resolvers_getBlockPatternCategories = () => async ({ + dispatch +}) => { + const categories = await external_wp_apiFetch_default()({ + path: '/wp/v2/block-patterns/categories' + }); + dispatch({ + type: 'RECEIVE_BLOCK_PATTERN_CATEGORIES', + categories + }); +}; +const resolvers_getUserPatternCategories = () => async ({ + dispatch, + resolveSelect +}) => { + const patternCategories = await resolveSelect.getEntityRecords('taxonomy', 'wp_pattern_category', { + per_page: -1, + _fields: 'id,name,description,slug', + context: 'view' + }); + const mappedPatternCategories = patternCategories?.map(userCategory => ({ + ...userCategory, + label: (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(userCategory.name), + name: userCategory.slug + })) || []; + dispatch({ + type: 'RECEIVE_USER_PATTERN_CATEGORIES', + patternCategories: mappedPatternCategories + }); +}; +const resolvers_getNavigationFallbackId = () => async ({ + dispatch, + select +}) => { + const fallback = await external_wp_apiFetch_default()({ + path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp-block-editor/v1/navigation-fallback', { + _embed: true + }) + }); + const record = fallback?._embedded?.self; + dispatch.receiveNavigationFallbackId(fallback?.id); + if (record) { + // If the fallback is already in the store, don't invalidate navigation queries. + // Otherwise, invalidate the cache for the scenario where there were no Navigation + // posts in the state and the fallback created one. + const existingFallbackEntityRecord = select.getEntityRecord('postType', 'wp_navigation', fallback.id); + const invalidateNavigationQueries = !existingFallbackEntityRecord; + dispatch.receiveEntityRecords('postType', 'wp_navigation', record, undefined, invalidateNavigationQueries); + + // Resolve to avoid further network requests. + dispatch.finishResolution('getEntityRecord', ['postType', 'wp_navigation', fallback.id]); + } +}; +const resolvers_getDefaultTemplateId = query => async ({ + dispatch +}) => { + const template = await external_wp_apiFetch_default()({ + path: (0,external_wp_url_namespaceObject.addQueryArgs)('/wp/v2/templates/lookup', query) + }); + // Endpoint may return an empty object if no template is found. + if (template?.id) { + dispatch.receiveDefaultTemplateId(query, template.id); + } +}; + +/** + * Requests an entity's revisions from the REST API. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch. + * @param {Object|undefined} query Optional object of query parameters to + * include with request. If requesting specific + * fields, fields must always include the ID. + */ +const resolvers_getRevisions = (kind, name, recordKey, query = {}) => async ({ + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.name === name && config.kind === kind); + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + if (query._fields) { + // If requesting specific fields, items and query association to said + // records are stored by ID reference. Thus, fields must always include + // the ID. + query = { + ...query, + _fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.revisionKey || DEFAULT_ENTITY_KEY])].join() + }; + } + const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.getRevisionsUrl(recordKey), query); + let records, response; + const meta = {}; + const isPaginated = entityConfig.supportsPagination && query.per_page !== -1; + try { + response = await external_wp_apiFetch_default()({ + path, + parse: !isPaginated + }); + } catch (error) { + // Do nothing if our request comes back with an API error. + return; + } + if (response) { + if (isPaginated) { + records = Object.values(await response.json()); + meta.totalItems = parseInt(response.headers.get('X-WP-Total')); + } else { + records = Object.values(response); + } + + // If we request fields but the result doesn't contain the fields, + // explicitly set these fields as "undefined" + // that way we consider the query "fulfilled". + if (query._fields) { + records = records.map(record => { + query._fields.split(',').forEach(field => { + if (!record.hasOwnProperty(field)) { + record[field] = undefined; + } + }); + return record; + }); + } + dispatch.receiveRevisions(kind, name, recordKey, records, query, false, meta); + + // When requesting all fields, the list of results can be used to + // resolve the `getRevision` selector in addition to `getRevisions`. + if (!query?._fields && !query.context) { + const key = entityConfig.key || DEFAULT_ENTITY_KEY; + const resolutionsArgs = records.filter(record => record[key]).map(record => [kind, name, recordKey, record[key]]); + dispatch({ + type: 'START_RESOLUTIONS', + selectorName: 'getRevision', + args: resolutionsArgs + }); + dispatch({ + type: 'FINISH_RESOLUTIONS', + selectorName: 'getRevision', + args: resolutionsArgs + }); + } + } +}; + +// Invalidate cache when a new revision is created. +resolvers_getRevisions.shouldInvalidate = (action, kind, name, recordKey) => action.type === 'SAVE_ENTITY_RECORD_FINISH' && name === action.name && kind === action.kind && !action.error && recordKey === action.recordId; + +/** + * Requests a specific Entity revision from the REST API. + * + * @param {string} kind Entity kind. + * @param {string} name Entity name. + * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch. + * @param {number|string} revisionKey The revision's key. + * @param {Object|undefined} query Optional object of query parameters to + * include with request. If requesting specific + * fields, fields must always include the ID. + */ +const resolvers_getRevision = (kind, name, recordKey, revisionKey, query) => async ({ + dispatch +}) => { + const configs = await dispatch(getOrLoadEntitiesConfig(kind, name)); + const entityConfig = configs.find(config => config.name === name && config.kind === kind); + if (!entityConfig || entityConfig?.__experimentalNoFetch) { + return; + } + if (query !== undefined && query._fields) { + // If requesting specific fields, items and query association to said + // records are stored by ID reference. Thus, fields must always include + // the ID. + query = { + ...query, + _fields: [...new Set([...(get_normalized_comma_separable(query._fields) || []), entityConfig.revisionKey || DEFAULT_ENTITY_KEY])].join() + }; + } + const path = (0,external_wp_url_namespaceObject.addQueryArgs)(entityConfig.getRevisionsUrl(recordKey, revisionKey), query); + let record; + try { + record = await external_wp_apiFetch_default()({ + path + }); + } catch (error) { + // Do nothing if our request comes back with an API error. + return; + } + if (record) { + dispatch.receiveRevisions(kind, name, recordKey, record, query); + } +}; + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/utils.js +function deepCopyLocksTreePath(tree, path) { + const newTree = { + ...tree + }; + let currentNode = newTree; + for (const branchName of path) { + currentNode.children = { + ...currentNode.children, + [branchName]: { + locks: [], + children: {}, + ...currentNode.children[branchName] + } + }; + currentNode = currentNode.children[branchName]; + } + return newTree; +} +function getNode(tree, path) { + let currentNode = tree; + for (const branchName of path) { + const nextNode = currentNode.children[branchName]; + if (!nextNode) { + return null; + } + currentNode = nextNode; + } + return currentNode; +} +function* iteratePath(tree, path) { + let currentNode = tree; + yield currentNode; + for (const branchName of path) { + const nextNode = currentNode.children[branchName]; + if (!nextNode) { + break; + } + yield nextNode; + currentNode = nextNode; + } +} +function* iterateDescendants(node) { + const stack = Object.values(node.children); + while (stack.length) { + const childNode = stack.pop(); + yield childNode; + stack.push(...Object.values(childNode.children)); + } +} +function hasConflictingLock({ + exclusive +}, locks) { + if (exclusive && locks.length) { + return true; + } + if (!exclusive && locks.filter(lock => lock.exclusive).length) { + return true; + } + return false; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/reducer.js +/** + * Internal dependencies + */ + +const DEFAULT_STATE = { + requests: [], + tree: { + locks: [], + children: {} + } +}; + +/** + * Reducer returning locks. + * + * @param {Object} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +function locks(state = DEFAULT_STATE, action) { + switch (action.type) { + case 'ENQUEUE_LOCK_REQUEST': + { + const { + request + } = action; + return { + ...state, + requests: [request, ...state.requests] + }; + } + case 'GRANT_LOCK_REQUEST': + { + const { + lock, + request + } = action; + const { + store, + path + } = request; + const storePath = [store, ...path]; + const newTree = deepCopyLocksTreePath(state.tree, storePath); + const node = getNode(newTree, storePath); + node.locks = [...node.locks, lock]; + return { + ...state, + requests: state.requests.filter(r => r !== request), + tree: newTree + }; + } + case 'RELEASE_LOCK': + { + const { + lock + } = action; + const storePath = [lock.store, ...lock.path]; + const newTree = deepCopyLocksTreePath(state.tree, storePath); + const node = getNode(newTree, storePath); + node.locks = node.locks.filter(l => l !== lock); + return { + ...state, + tree: newTree + }; + } + } + return state; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/selectors.js +/** + * Internal dependencies + */ + +function getPendingLockRequests(state) { + return state.requests; +} +function isLockAvailable(state, store, path, { + exclusive +}) { + const storePath = [store, ...path]; + const locks = state.tree; + + // Validate all parents and the node itself + for (const node of iteratePath(locks, storePath)) { + if (hasConflictingLock({ + exclusive + }, node.locks)) { + return false; + } + } + + // iteratePath terminates early if path is unreachable, let's + // re-fetch the node and check it exists in the tree. + const node = getNode(locks, storePath); + if (!node) { + return true; + } + + // Validate all nested nodes + for (const descendant of iterateDescendants(node)) { + if (hasConflictingLock({ + exclusive + }, descendant.locks)) { + return false; + } + } + return true; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/engine.js +/** + * Internal dependencies + */ + + +function createLocks() { + let state = locks(undefined, { + type: '@@INIT' + }); + function processPendingLockRequests() { + for (const request of getPendingLockRequests(state)) { + const { + store, + path, + exclusive, + notifyAcquired + } = request; + if (isLockAvailable(state, store, path, { + exclusive + })) { + const lock = { + store, + path, + exclusive + }; + state = locks(state, { + type: 'GRANT_LOCK_REQUEST', + lock, + request + }); + notifyAcquired(lock); + } + } + } + function acquire(store, path, exclusive) { + return new Promise(resolve => { + state = locks(state, { + type: 'ENQUEUE_LOCK_REQUEST', + request: { + store, + path, + exclusive, + notifyAcquired: resolve + } + }); + processPendingLockRequests(); + }); + } + function release(lock) { + state = locks(state, { + type: 'RELEASE_LOCK', + lock + }); + processPendingLockRequests(); + } + return { + acquire, + release + }; +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/locks/actions.js +/** + * Internal dependencies + */ + +function createLocksActions() { + const locks = createLocks(); + function __unstableAcquireStoreLock(store, path, { + exclusive + }) { + return () => locks.acquire(store, path, exclusive); + } + function __unstableReleaseStoreLock(lock) { + return () => locks.release(lock); + } + return { + __unstableAcquireStoreLock, + __unstableReleaseStoreLock + }; +} + +;// CONCATENATED MODULE: external ["wp","privateApis"] +const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"]; +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/private-apis.js +/** + * WordPress dependencies + */ + +const { + lock, + unlock +} = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/core-data'); + +;// CONCATENATED MODULE: external ["wp","element"] +const external_wp_element_namespaceObject = window["wp"]["element"]; +;// CONCATENATED MODULE: external ["wp","blocks"] +const external_wp_blocks_namespaceObject = window["wp"]["blocks"]; +;// CONCATENATED MODULE: external ["wp","blockEditor"] +const external_wp_blockEditor_namespaceObject = window["wp"]["blockEditor"]; +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/get-rich-text-values-cached.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + +// TODO: The following line should have been: +// +// const unlockedApis = unlock( blockEditorPrivateApis ); +// +// But there are hidden circular dependencies in RNMobile code, specifically in +// certain native components in the `components` package that depend on +// `block-editor`. What follows is a workaround that defers the `unlock` call +// to prevent native code from failing. +// +// Fix once https://github.com/WordPress/gutenberg/issues/52692 is closed. +let unlockedApis; +const cache = new WeakMap(); +function getRichTextValuesCached(block) { + if (!unlockedApis) { + unlockedApis = unlock(external_wp_blockEditor_namespaceObject.privateApis); + } + if (!cache.has(block)) { + const values = unlockedApis.getRichTextValues([block]); + cache.set(block, values); + } + return cache.get(block); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/get-footnotes-order.js +/** + * Internal dependencies + */ + +const get_footnotes_order_cache = new WeakMap(); +function getBlockFootnotesOrder(block) { + if (!get_footnotes_order_cache.has(block)) { + const order = []; + for (const value of getRichTextValuesCached(block)) { + if (!value) { + continue; + } + + // replacements is a sparse array, use forEach to skip empty slots. + value.replacements.forEach(({ + type, + attributes + }) => { + if (type === 'core/footnote') { + order.push(attributes['data-fn']); + } + }); + } + get_footnotes_order_cache.set(block, order); + } + return get_footnotes_order_cache.get(block); +} +function getFootnotesOrder(blocks) { + // We can only separate getting order from blocks at the root level. For + // deeper inner blocks, this will not work since it's possible to have both + // inner blocks and block attributes, so order needs to be computed from the + // Edit functions as a whole. + return blocks.flatMap(getBlockFootnotesOrder); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/footnotes/index.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + +let oldFootnotes = {}; +function updateFootnotesFromMeta(blocks, meta) { + const output = { + blocks + }; + if (!meta) { + return output; + } + + // If meta.footnotes is empty, it means the meta is not registered. + if (meta.footnotes === undefined) { + return output; + } + const newOrder = getFootnotesOrder(blocks); + const footnotes = meta.footnotes ? JSON.parse(meta.footnotes) : []; + const currentOrder = footnotes.map(fn => fn.id); + if (currentOrder.join('') === newOrder.join('')) { + return output; + } + const newFootnotes = newOrder.map(fnId => footnotes.find(fn => fn.id === fnId) || oldFootnotes[fnId] || { + id: fnId, + content: '' + }); + function updateAttributes(attributes) { + // Only attempt to update attributes, if attributes is an object. + if (!attributes || Array.isArray(attributes) || typeof attributes !== 'object') { + return attributes; + } + attributes = { + ...attributes + }; + for (const key in attributes) { + const value = attributes[key]; + if (Array.isArray(value)) { + attributes[key] = value.map(updateAttributes); + continue; + } + + // To do, remove support for string values? + if (typeof value !== 'string' && !(value instanceof external_wp_richText_namespaceObject.RichTextData)) { + continue; + } + const richTextValue = typeof value === 'string' ? external_wp_richText_namespaceObject.RichTextData.fromHTMLString(value) : new external_wp_richText_namespaceObject.RichTextData(value); + richTextValue.replacements.forEach(replacement => { + if (replacement.type === 'core/footnote') { + const id = replacement.attributes['data-fn']; + const index = newOrder.indexOf(id); + // The innerHTML contains the count wrapped in a link. + const countValue = (0,external_wp_richText_namespaceObject.create)({ + html: replacement.innerHTML + }); + countValue.text = String(index + 1); + countValue.formats = Array.from({ + length: countValue.text.length + }, () => countValue.formats[0]); + countValue.replacements = Array.from({ + length: countValue.text.length + }, () => countValue.replacements[0]); + replacement.innerHTML = (0,external_wp_richText_namespaceObject.toHTMLString)({ + value: countValue + }); + } + }); + attributes[key] = typeof value === 'string' ? richTextValue.toHTMLString() : richTextValue; + } + return attributes; + } + function updateBlocksAttributes(__blocks) { + return __blocks.map(block => { + return { + ...block, + attributes: updateAttributes(block.attributes), + innerBlocks: updateBlocksAttributes(block.innerBlocks) + }; + }); + } + + // We need to go through all block attributes deeply and update the + // footnote anchor numbering (textContent) to match the new order. + const newBlocks = updateBlocksAttributes(blocks); + oldFootnotes = { + ...oldFootnotes, + ...footnotes.reduce((acc, fn) => { + if (!newOrder.includes(fn.id)) { + acc[fn.id] = fn; + } + return acc; + }, {}) + }; + return { + meta: { + ...meta, + footnotes: JSON.stringify(newFootnotes) + }, + blocks: newBlocks + }; +} + +;// CONCATENATED MODULE: external "ReactJSXRuntime" +const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"]; +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/entity-provider.js +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + + +/** @typedef {import('@wordpress/blocks').WPBlock} WPBlock */ + +const EMPTY_ARRAY = []; +const EntityContext = (0,external_wp_element_namespaceObject.createContext)({}); + +/** + * Context provider component for providing + * an entity for a specific entity. + * + * @param {Object} props The component's props. + * @param {string} props.kind The entity kind. + * @param {string} props.type The entity name. + * @param {number} props.id The entity ID. + * @param {*} props.children The children to wrap. + * + * @return {Object} The provided children, wrapped with + * the entity's context provider. + */ +function EntityProvider({ + kind, + type: name, + id, + children +}) { + const parent = (0,external_wp_element_namespaceObject.useContext)(EntityContext); + const childContext = (0,external_wp_element_namespaceObject.useMemo)(() => ({ + ...parent, + [kind]: { + ...parent?.[kind], + [name]: id + } + }), [parent, kind, name, id]); + return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(EntityContext.Provider, { + value: childContext, + children: children + }); +} + +/** + * Hook that returns the ID for the nearest + * provided entity of the specified type. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + */ +function useEntityId(kind, name) { + const context = (0,external_wp_element_namespaceObject.useContext)(EntityContext); + return context?.[kind]?.[name]; +} + +/** + * Hook that returns the value and a setter for the + * specified property of the nearest provided + * entity of the specified type. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + * @param {string} prop The property name. + * @param {string} [_id] An entity ID to use instead of the context-provided one. + * + * @return {[*, Function, *]} An array where the first item is the + * property value, the second is the + * setter and the third is the full value + * object from REST API containing more + * information like `raw`, `rendered` and + * `protected` props. + */ +function useEntityProp(kind, name, prop, _id) { + const providerId = useEntityId(kind, name); + const id = _id !== null && _id !== void 0 ? _id : providerId; + const { + value, + fullValue + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + const { + getEntityRecord, + getEditedEntityRecord + } = select(STORE_NAME); + const record = getEntityRecord(kind, name, id); // Trigger resolver. + const editedRecord = getEditedEntityRecord(kind, name, id); + return record && editedRecord ? { + value: editedRecord[prop], + fullValue: record[prop] + } : {}; + }, [kind, name, id, prop]); + const { + editEntityRecord + } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); + const setValue = (0,external_wp_element_namespaceObject.useCallback)(newValue => { + editEntityRecord(kind, name, id, { + [prop]: newValue + }); + }, [editEntityRecord, kind, name, id, prop]); + return [value, setValue, fullValue]; +} +const parsedBlocksCache = new WeakMap(); + +/** + * Hook that returns block content getters and setters for + * the nearest provided entity of the specified type. + * + * The return value has the shape `[ blocks, onInput, onChange ]`. + * `onInput` is for block changes that don't create undo levels + * or dirty the post, non-persistent changes, and `onChange` is for + * persistent changes. They map directly to the props of a + * `BlockEditorProvider` and are intended to be used with it, + * or similar components or hooks. + * + * @param {string} kind The entity kind. + * @param {string} name The entity name. + * @param {Object} options + * @param {string} [options.id] An entity ID to use instead of the context-provided one. + * + * @return {[WPBlock[], Function, Function]} The block array and setters. + */ +function useEntityBlockEditor(kind, name, { + id: _id +} = {}) { + const providerId = useEntityId(kind, name); + const id = _id !== null && _id !== void 0 ? _id : providerId; + const { + getEntityRecord, + getEntityRecordEdits + } = (0,external_wp_data_namespaceObject.useSelect)(STORE_NAME); + const { + content, + editedBlocks, + meta + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + if (!id) { + return {}; + } + const { + getEditedEntityRecord + } = select(STORE_NAME); + const editedRecord = getEditedEntityRecord(kind, name, id); + return { + editedBlocks: editedRecord.blocks, + content: editedRecord.content, + meta: editedRecord.meta + }; + }, [kind, name, id]); + const { + __unstableCreateUndoLevel, + editEntityRecord + } = (0,external_wp_data_namespaceObject.useDispatch)(STORE_NAME); + const blocks = (0,external_wp_element_namespaceObject.useMemo)(() => { + if (!id) { + return undefined; + } + if (editedBlocks) { + return editedBlocks; + } + if (!content || typeof content !== 'string') { + return EMPTY_ARRAY; + } + + // If there's an edit, cache the parsed blocks by the edit. + // If not, cache by the original enity record. + const edits = getEntityRecordEdits(kind, name, id); + const isUnedited = !edits || !Object.keys(edits).length; + const cackeKey = isUnedited ? getEntityRecord(kind, name, id) : edits; + let _blocks = parsedBlocksCache.get(cackeKey); + if (!_blocks) { + _blocks = (0,external_wp_blocks_namespaceObject.parse)(content); + parsedBlocksCache.set(cackeKey, _blocks); + } + return _blocks; + }, [kind, name, id, editedBlocks, content, getEntityRecord, getEntityRecordEdits]); + const updateFootnotes = (0,external_wp_element_namespaceObject.useCallback)(_blocks => updateFootnotesFromMeta(_blocks, meta), [meta]); + const onChange = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { + const noChange = blocks === newBlocks; + if (noChange) { + return __unstableCreateUndoLevel(kind, name, id); + } + const { + selection, + ...rest + } = options; + + // We create a new function here on every persistent edit + // to make sure the edit makes the post dirty and creates + // a new undo level. + const edits = { + selection, + content: ({ + blocks: blocksForSerialization = [] + }) => (0,external_wp_blocks_namespaceObject.__unstableSerializeAndClean)(blocksForSerialization), + ...updateFootnotes(newBlocks) + }; + editEntityRecord(kind, name, id, edits, { + isCached: false, + ...rest + }); + }, [kind, name, id, blocks, updateFootnotes, __unstableCreateUndoLevel, editEntityRecord]); + const onInput = (0,external_wp_element_namespaceObject.useCallback)((newBlocks, options) => { + const { + selection, + ...rest + } = options; + const footnotesChanges = updateFootnotes(newBlocks); + const edits = { + selection, + ...footnotesChanges + }; + editEntityRecord(kind, name, id, edits, { + isCached: true, + ...rest + }); + }, [kind, name, id, updateFootnotes, editEntityRecord]); + return [blocks, onInput, onChange]; +} + +;// CONCATENATED MODULE: ./node_modules/memize/dist/index.js +/** + * Memize options object. + * + * @typedef MemizeOptions + * + * @property {number} [maxSize] Maximum size of the cache. + */ + +/** + * Internal cache entry. + * + * @typedef MemizeCacheNode + * + * @property {?MemizeCacheNode|undefined} [prev] Previous node. + * @property {?MemizeCacheNode|undefined} [next] Next node. + * @property {Array<*>} args Function arguments for cache + * entry. + * @property {*} val Function result. + */ + +/** + * Properties of the enhanced function for controlling cache. + * + * @typedef MemizeMemoizedFunction + * + * @property {()=>void} clear Clear the cache. + */ + +/** + * Accepts a function to be memoized, and returns a new memoized function, with + * optional options. + * + * @template {(...args: any[]) => any} F + * + * @param {F} fn Function to memoize. + * @param {MemizeOptions} [options] Options object. + * + * @return {((...args: Parameters) => ReturnType) & MemizeMemoizedFunction} Memoized function. + */ +function memize(fn, options) { + var size = 0; + + /** @type {?MemizeCacheNode|undefined} */ + var head; + + /** @type {?MemizeCacheNode|undefined} */ + var tail; + + options = options || {}; + + function memoized(/* ...args */) { + var node = head, + len = arguments.length, + args, + i; + + searchCache: while (node) { + // Perform a shallow equality test to confirm that whether the node + // under test is a candidate for the arguments passed. Two arrays + // are shallowly equal if their length matches and each entry is + // strictly equal between the two sets. Avoid abstracting to a + // function which could incur an arguments leaking deoptimization. + + // Check whether node arguments match arguments length + if (node.args.length !== arguments.length) { + node = node.next; + continue; + } + + // Check whether node arguments match arguments values + for (i = 0; i < len; i++) { + if (node.args[i] !== arguments[i]) { + node = node.next; + continue searchCache; + } + } + + // At this point we can assume we've found a match + + // Surface matched node to head if not already + if (node !== head) { + // As tail, shift to previous. Must only shift if not also + // head, since if both head and tail, there is no previous. + if (node === tail) { + tail = node.prev; + } + + // Adjust siblings to point to each other. If node was tail, + // this also handles new tail's empty `next` assignment. + /** @type {MemizeCacheNode} */ (node.prev).next = node.next; + if (node.next) { + node.next.prev = node.prev; + } + + node.next = head; + node.prev = null; + /** @type {MemizeCacheNode} */ (head).prev = node; + head = node; + } + + // Return immediately + return node.val; + } + + // No cached value found. Continue to insertion phase: + + // Create a copy of arguments (avoid leaking deoptimization) + args = new Array(len); + for (i = 0; i < len; i++) { + args[i] = arguments[i]; + } + + node = { + args: args, + + // Generate the result from original function + val: fn.apply(null, args), + }; + + // Don't need to check whether node is already head, since it would + // have been returned above already if it was + + // Shift existing head down list + if (head) { + head.prev = node; + node.next = head; + } else { + // If no head, follows that there's no tail (at initial or reset) + tail = node; + } + + // Trim tail if we're reached max size and are pending cache insertion + if (size === /** @type {MemizeOptions} */ (options).maxSize) { + tail = /** @type {MemizeCacheNode} */ (tail).prev; + /** @type {MemizeCacheNode} */ (tail).next = null; + } else { + size++; + } + + head = node; + + return node.val; + } + + memoized.clear = function () { + head = null; + tail = null; + size = 0; + }; + + // Ignore reason: There's not a clear solution to create an intersection of + // the function with additional properties, where the goal is to retain the + // function signature of the incoming argument and add control properties + // on the return value. + + // @ts-ignore + return memoized; +} + + + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/memoize.js +/** + * External dependencies + */ + + +// re-export due to restrictive esModuleInterop setting +/* harmony default export */ const memoize = (memize); + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/constants.js +let Status = /*#__PURE__*/function (Status) { + Status["Idle"] = "IDLE"; + Status["Resolving"] = "RESOLVING"; + Status["Error"] = "ERROR"; + Status["Success"] = "SUCCESS"; + return Status; +}({}); + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-query-select.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + +const META_SELECTORS = ['getIsResolving', 'hasStartedResolution', 'hasFinishedResolution', 'isResolving', 'getCachedResolvers']; +/** + * Like useSelect, but the selectors return objects containing + * both the original data AND the resolution info. + * + * @since 6.1.0 Introduced in WordPress core. + * @private + * + * @param {Function} mapQuerySelect see useSelect + * @param {Array} deps see useSelect + * + * @example + * ```js + * import { useQuerySelect } from '@wordpress/data'; + * import { store as coreDataStore } from '@wordpress/core-data'; + * + * function PageTitleDisplay( { id } ) { + * const { data: page, isResolving } = useQuerySelect( ( query ) => { + * return query( coreDataStore ).getEntityRecord( 'postType', 'page', id ) + * }, [ id ] ); + * + * if ( isResolving ) { + * return 'Loading...'; + * } + * + * return page.title; + * } + * + * // Rendered in the application: + * // + * ``` + * + * In the above example, when `PageTitleDisplay` is rendered into an + * application, the page and the resolution details will be retrieved from + * the store state using the `mapSelect` callback on `useQuerySelect`. + * + * If the id prop changes then any page in the state for that id is + * retrieved. If the id prop doesn't change and other props are passed in + * that do change, the title will not change because the dependency is just + * the id. + * @see useSelect + * + * @return {QuerySelectResponse} Queried data. + */ +function useQuerySelect(mapQuerySelect, deps) { + return (0,external_wp_data_namespaceObject.useSelect)((select, registry) => { + const resolve = store => enrichSelectors(select(store)); + return mapQuerySelect(resolve, registry); + }, deps); +} +/** + * Transform simple selectors into ones that return an object with the + * original return value AND the resolution info. + * + * @param {Object} selectors Selectors to enrich + * @return {EnrichedSelectors} Enriched selectors + */ +const enrichSelectors = memoize(selectors => { + const resolvers = {}; + for (const selectorName in selectors) { + if (META_SELECTORS.includes(selectorName)) { + continue; + } + Object.defineProperty(resolvers, selectorName, { + get: () => (...args) => { + const data = selectors[selectorName](...args); + const resolutionStatus = selectors.getResolutionState(selectorName, args)?.status; + let status; + switch (resolutionStatus) { + case 'resolving': + status = Status.Resolving; + break; + case 'finished': + status = Status.Success; + break; + case 'error': + status = Status.Error; + break; + case undefined: + status = Status.Idle; + break; + } + return { + data, + status, + isResolving: status === Status.Resolving, + hasStarted: status !== Status.Idle, + hasResolved: status === Status.Success || status === Status.Error + }; + } + }); + } + return resolvers; +}); + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-record.js +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + +const use_entity_record_EMPTY_OBJECT = {}; + +/** + * Resolves the specified entity record. + * + * @since 6.1.0 Introduced in WordPress core. + * + * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds. + * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names. + * @param recordId ID of the requested entity record. + * @param options Optional hook options. + * @example + * ```js + * import { useEntityRecord } from '@wordpress/core-data'; + * + * function PageTitleDisplay( { id } ) { + * const { record, isResolving } = useEntityRecord( 'postType', 'page', id ); + * + * if ( isResolving ) { + * return 'Loading...'; + * } + * + * return record.title; + * } + * + * // Rendered in the application: + * // + * ``` + * + * In the above example, when `PageTitleDisplay` is rendered into an + * application, the page and the resolution details will be retrieved from + * the store state using `getEntityRecord()`, or resolved if missing. + * + * @example + * ```js + * import { useCallback } from 'react'; + * import { useDispatch } from '@wordpress/data'; + * import { __ } from '@wordpress/i18n'; + * import { TextControl } from '@wordpress/components'; + * import { store as noticeStore } from '@wordpress/notices'; + * import { useEntityRecord } from '@wordpress/core-data'; + * + * function PageRenameForm( { id } ) { + * const page = useEntityRecord( 'postType', 'page', id ); + * const { createSuccessNotice, createErrorNotice } = + * useDispatch( noticeStore ); + * + * const setTitle = useCallback( ( title ) => { + * page.edit( { title } ); + * }, [ page.edit ] ); + * + * if ( page.isResolving ) { + * return 'Loading...'; + * } + * + * async function onRename( event ) { + * event.preventDefault(); + * try { + * await page.save(); + * createSuccessNotice( __( 'Page renamed.' ), { + * type: 'snackbar', + * } ); + * } catch ( error ) { + * createErrorNotice( error.message, { type: 'snackbar' } ); + * } + * } + * + * return ( + *
+ * + * + * + * ); + * } + * + * // Rendered in the application: + * // + * ``` + * + * In the above example, updating and saving the page title is handled + * via the `edit()` and `save()` mutation helpers provided by + * `useEntityRecord()`; + * + * @return Entity record data. + * @template RecordType + */ +function useEntityRecord(kind, name, recordId, options = { + enabled: true +}) { + const { + editEntityRecord, + saveEditedEntityRecord + } = (0,external_wp_data_namespaceObject.useDispatch)(store); + const mutations = (0,external_wp_element_namespaceObject.useMemo)(() => ({ + edit: (record, editOptions = {}) => editEntityRecord(kind, name, recordId, record, editOptions), + save: (saveOptions = {}) => saveEditedEntityRecord(kind, name, recordId, { + throwOnError: true, + ...saveOptions + }) + }), [editEntityRecord, kind, name, recordId, saveEditedEntityRecord]); + const { + editedRecord, + hasEdits, + edits + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + if (!options.enabled) { + return { + editedRecord: use_entity_record_EMPTY_OBJECT, + hasEdits: false, + edits: use_entity_record_EMPTY_OBJECT + }; + } + return { + editedRecord: select(store).getEditedEntityRecord(kind, name, recordId), + hasEdits: select(store).hasEditsForEntityRecord(kind, name, recordId), + edits: select(store).getEntityRecordNonTransientEdits(kind, name, recordId) + }; + }, [kind, name, recordId, options.enabled]); + const { + data: record, + ...querySelectRest + } = useQuerySelect(query => { + if (!options.enabled) { + return { + data: null + }; + } + return query(store).getEntityRecord(kind, name, recordId); + }, [kind, name, recordId, options.enabled]); + return { + record, + editedRecord, + hasEdits, + edits, + ...querySelectRest, + ...mutations + }; +} +function __experimentalUseEntityRecord(kind, name, recordId, options) { + external_wp_deprecated_default()(`wp.data.__experimentalUseEntityRecord`, { + alternative: 'wp.data.useEntityRecord', + since: '6.1' + }); + return useEntityRecord(kind, name, recordId, options); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-entity-records.js +/** + * WordPress dependencies + */ + + + + +/** + * Internal dependencies + */ + + +const use_entity_records_EMPTY_ARRAY = []; + +/** + * Resolves the specified entity records. + * + * @since 6.1.0 Introduced in WordPress core. + * + * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds. + * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names. + * @param queryArgs Optional HTTP query description for how to fetch the data, passed to the requested API endpoint. + * @param options Optional hook options. + * @example + * ```js + * import { useEntityRecords } from '@wordpress/core-data'; + * + * function PageTitlesList() { + * const { records, isResolving } = useEntityRecords( 'postType', 'page' ); + * + * if ( isResolving ) { + * return 'Loading...'; + * } + * + * return ( + *
    + * {records.map(( page ) => ( + *
  • { page.title }
  • + * ))} + *
+ * ); + * } + * + * // Rendered in the application: + * // + * ``` + * + * In the above example, when `PageTitlesList` is rendered into an + * application, the list of records and the resolution details will be retrieved from + * the store state using `getEntityRecords()`, or resolved if missing. + * + * @return Entity records data. + * @template RecordType + */ +function useEntityRecords(kind, name, queryArgs = {}, options = { + enabled: true +}) { + // Serialize queryArgs to a string that can be safely used as a React dep. + // We can't just pass queryArgs as one of the deps, because if it is passed + // as an object literal, then it will be a different object on each call even + // if the values remain the same. + const queryAsString = (0,external_wp_url_namespaceObject.addQueryArgs)('', queryArgs); + const { + data: records, + ...rest + } = useQuerySelect(query => { + if (!options.enabled) { + return { + // Avoiding returning a new reference on every execution. + data: use_entity_records_EMPTY_ARRAY + }; + } + return query(store).getEntityRecords(kind, name, queryArgs); + }, [kind, name, queryAsString, options.enabled]); + const { + totalItems, + totalPages + } = (0,external_wp_data_namespaceObject.useSelect)(select => { + if (!options.enabled) { + return { + totalItems: null, + totalPages: null + }; + } + return { + totalItems: select(store).getEntityRecordsTotalItems(kind, name, queryArgs), + totalPages: select(store).getEntityRecordsTotalPages(kind, name, queryArgs) + }; + }, [kind, name, queryAsString, options.enabled]); + return { + records, + totalItems, + totalPages, + ...rest + }; +} +function __experimentalUseEntityRecords(kind, name, queryArgs, options) { + external_wp_deprecated_default()(`wp.data.__experimentalUseEntityRecords`, { + alternative: 'wp.data.useEntityRecords', + since: '6.1' + }); + return useEntityRecords(kind, name, queryArgs, options); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/use-resource-permissions.js +/** + * WordPress dependencies + */ + + +/** + * Internal dependencies + */ + + + + +/** + * Is the data resolved by now? + */ + +/** + * Resolves resource permissions. + * + * @since 6.1.0 Introduced in WordPress core. + * + * @param resource The resource in question, e.g. media. + * @param id ID of a specific resource entry, if needed, e.g. 10. + * + * @example + * ```js + * import { useResourcePermissions } from '@wordpress/core-data'; + * + * function PagesList() { + * const { canCreate, isResolving } = useResourcePermissions( 'pages' ); + * + * if ( isResolving ) { + * return 'Loading ...'; + * } + * + * return ( + *
+ * {canCreate ? () : false} + * // ... + *
+ * ); + * } + * + * // Rendered in the application: + * // + * ``` + * + * @example + * ```js + * import { useResourcePermissions } from '@wordpress/core-data'; + * + * function Page({ pageId }) { + * const { + * canCreate, + * canUpdate, + * canDelete, + * isResolving + * } = useResourcePermissions( 'pages', pageId ); + * + * if ( isResolving ) { + * return 'Loading ...'; + * } + * + * return ( + *
+ * {canCreate ? () : false} + * {canUpdate ? () : false} + * {canDelete ? () : false} + * // ... + *
+ * ); + * } + * + * // Rendered in the application: + * // + * ``` + * + * In the above example, when `PagesList` is rendered into an + * application, the appropriate permissions and the resolution details will be retrieved from + * the store state using `canUser()`, or resolved if missing. + * + * @return Entity records data. + * @template IdType + */ +function useResourcePermissions(resource, id) { + return useQuerySelect(resolve => { + const { + canUser + } = resolve(store); + const create = canUser('create', resource); + if (!id) { + const read = canUser('read', resource); + const isResolving = create.isResolving || read.isResolving; + const hasResolved = create.hasResolved && read.hasResolved; + let status = Status.Idle; + if (isResolving) { + status = Status.Resolving; + } else if (hasResolved) { + status = Status.Success; + } + return { + status, + isResolving, + hasResolved, + canCreate: create.hasResolved && create.data, + canRead: read.hasResolved && read.data + }; + } + const read = canUser('read', resource, id); + const update = canUser('update', resource, id); + const _delete = canUser('delete', resource, id); + const isResolving = read.isResolving || create.isResolving || update.isResolving || _delete.isResolving; + const hasResolved = read.hasResolved && create.hasResolved && update.hasResolved && _delete.hasResolved; + let status = Status.Idle; + if (isResolving) { + status = Status.Resolving; + } else if (hasResolved) { + status = Status.Success; + } + return { + status, + isResolving, + hasResolved, + canRead: hasResolved && read.data, + canCreate: hasResolved && create.data, + canUpdate: hasResolved && update.data, + canDelete: hasResolved && _delete.data + }; + }, [resource, id]); +} +function __experimentalUseResourcePermissions(resource, id) { + external_wp_deprecated_default()(`wp.data.__experimentalUseResourcePermissions`, { + alternative: 'wp.data.useResourcePermissions', + since: '6.1' + }); + return useResourcePermissions(resource, id); +} + +;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/hooks/index.js + @@ -6306,6 +7858,7 @@ * WordPress dependencies */ + /** * Internal dependencies */ @@ -6316,90 +7869,83 @@ - // The entity selectors/resolvers and actions are shortcuts to their generic equivalents + + + +// The entity selectors/resolvers and actions are shortcuts to their generic equivalents // (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords) // Instead of getEntityRecord, the consumer could use more user-friendly named selector: getPostType, getTaxonomy... // The "kind" and the "name" of the entity are combined to generate these shortcuts. - -const entitySelectors = rootEntitiesConfig.reduce((result, entity) => { +const build_module_entitiesConfig = [...rootEntitiesConfig, ...additionalEntityConfigLoaders.filter(config => !!config.name)]; +const entitySelectors = build_module_entitiesConfig.reduce((result, entity) => { const { kind, - name + name, + plural } = entity; - result[getMethodName(kind, name)] = (state, key, query) => getEntityRecord(state, kind, name, key, query); - - result[getMethodName(kind, name, 'get', true)] = (state, query) => getEntityRecords(state, kind, name, query); - + if (plural) { + result[getMethodName(kind, plural, 'get')] = (state, query) => getEntityRecords(state, kind, name, query); + } return result; }, {}); -const entityResolvers = rootEntitiesConfig.reduce((result, entity) => { +const entityResolvers = build_module_entitiesConfig.reduce((result, entity) => { + const { + kind, + name, + plural + } = entity; + result[getMethodName(kind, name)] = (key, query) => resolvers_getEntityRecord(kind, name, key, query); + if (plural) { + const pluralMethodName = getMethodName(kind, plural, 'get'); + result[pluralMethodName] = (...args) => resolvers_getEntityRecords(kind, name, ...args); + result[pluralMethodName].shouldInvalidate = action => resolvers_getEntityRecords.shouldInvalidate(action, kind, name); + } + return result; +}, {}); +const entityActions = build_module_entitiesConfig.reduce((result, entity) => { const { kind, name } = entity; - - result[getMethodName(kind, name)] = (key, query) => resolvers_getEntityRecord(kind, name, key, query); - - const pluralMethodName = getMethodName(kind, name, 'get', true); - - result[pluralMethodName] = function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - return resolvers_getEntityRecords(kind, name, ...args); - }; - - result[pluralMethodName].shouldInvalidate = action => resolvers_getEntityRecords.shouldInvalidate(action, kind, name); - + result[getMethodName(kind, name, 'save')] = (record, options) => saveEntityRecord(kind, name, record, options); + result[getMethodName(kind, name, 'delete')] = (key, query, options) => deleteEntityRecord(kind, name, key, query, options); return result; }, {}); -const entityActions = rootEntitiesConfig.reduce((result, entity) => { - const { - kind, - name - } = entity; - - result[getMethodName(kind, name, 'save')] = key => saveEntityRecord(kind, name, key); - - result[getMethodName(kind, name, 'delete')] = (key, query) => deleteEntityRecord(kind, name, key, query); - - return result; -}, {}); - const storeConfig = () => ({ reducer: build_module_reducer, - actions: { ...build_module_actions_namespaceObject, + actions: { + ...build_module_actions_namespaceObject, ...entityActions, ...createLocksActions() }, - selectors: { ...build_module_selectors_namespaceObject, + selectors: { + ...build_module_selectors_namespaceObject, ...entitySelectors }, - resolvers: { ...resolvers_namespaceObject, + resolvers: { + ...resolvers_namespaceObject, ...entityResolvers } }); + /** * Store definition for the code data namespace. * * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore - * - * @type {Object} - */ - - + */ const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, storeConfig()); -(0,external_wp_data_namespaceObject.register)(store); - - - - - - - -}(); +unlock(store).registerPrivateSelectors(private_selectors_namespaceObject); +(0,external_wp_data_namespaceObject.register)(store); // Register store after unlocking private selectors to allow resolvers to use them. + + + + + + + +})(); + (window.wp = window.wp || {}).coreData = __webpack_exports__; /******/ })() ; \ No newline at end of file