UNPKG

@wordpress/server-side-render

Version:

The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.

8 lines (7 loc) 7.97 kB
{ "version": 3, "sources": ["../src/server-side-render.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tRawHTML,\n\tuseEffect,\n\tuseState,\n\tuseRef,\n\tuseMemo,\n} from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { useServerSideRender } from './hook';\n\nconst EMPTY_OBJECT = {};\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { message, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tmessage\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children } ) {\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\n\tuseEffect( () => {\n\t\t// Schedule showing the Spinner after 1 second.\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [] );\n\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport function ServerSideRender( props ) {\n\tconst prevContentRef = useRef( '' );\n\tconst {\n\t\tclassName,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t\t...restProps\n\t} = props;\n\n\tconst { content, status, error } = useServerSideRender( restProps );\n\n\t// Store the previous successful HTML response to show while loading.\n\tuseEffect( () => {\n\t\tif ( content ) {\n\t\t\tprevContentRef.current = content;\n\t\t}\n\t}, [ content ] );\n\n\tif ( status === 'loading' ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props }>\n\t\t\t\t{ !! prevContentRef.current && (\n\t\t\t\t\t<RawHTML className={ className }>\n\t\t\t\t\t\t{ prevContentRef.current }\n\t\t\t\t\t</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\tif ( status === 'success' && ! content ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( status === 'error' ) {\n\t\treturn <ErrorResponsePlaceholder message={ error } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ content }</RawHTML>;\n}\n\n/**\n * A component that renders server-side content for blocks.\n *\n * Note: URL query will include the current post ID when applicable.\n * This is useful for blocks that depend on the context of the current post for rendering.\n *\n * @example\n * ```jsx\n * import { ServerSideRender } from '@wordpress/server-side-render';\n * // Legacy import for WordPress 6.8 and earlier\n * // import { default as ServerSideRender } from '@wordpress/server-side-render';\n *\n * function Example() {\n * return (\n * <ServerSideRender\n * block=\"core/archives\"\n * attributes={ { showPostCounts: true } }\n * urlQueryArgs={ { customArg: 'value' } }\n * className=\"custom-class\"\n * />\n * );\n * }\n * ```\n *\n * @param {Object} props Component props.\n * @param {string} props.block The identifier of the block to be serverside rendered.\n * @param {Object} props.attributes The block attributes to be sent to the server for rendering.\n * @param {string} [props.className] Additional classes to apply to the wrapper element.\n * @param {string} [props.httpMethod='GET'] The HTTP method to use ('GET' or 'POST'). Default is 'GET'\n * @param {Object} [props.urlQueryArgs] Additional query arguments to append to the request URL.\n * @param {boolean} [props.skipBlockSupportAttributes=false] Whether to remove block support attributes before sending.\n * @param {Function} [props.EmptyResponsePlaceholder] Component rendered when the API response is empty.\n * @param {Function} [props.ErrorResponsePlaceholder] Component rendered when the API response is an error.\n * @param {Function} [props.LoadingResponsePlaceholder] Component rendered while the API request is loading.\n *\n * @return {React.JSX.Element} The rendered server-side content.\n */\nexport function ServerSideRenderWithPostId( {\n\turlQueryArgs = EMPTY_OBJECT,\n\t...props\n} ) {\n\tconst currentPostId = useSelect( ( select ) => {\n\t\t// FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.\n\t\t// It is used by blocks that can be loaded into a *non-post* block editor.\n\t\t// eslint-disable-next-line @wordpress/data-no-store-string-literals\n\t\tconst postId = select( 'core/editor' )?.getCurrentPostId();\n\n\t\t// For templates and template parts we use a custom ID format.\n\t\t// Since they aren't real posts, we don't want to use their ID\n\t\t// for server-side rendering. Since they use a string based ID,\n\t\t// we can assume real post IDs are numbers.\n\t\treturn postId && typeof postId === 'number' ? postId : null;\n\t}, [] );\n\n\tconst newUrlQueryArgs = useMemo( () => {\n\t\tif ( ! currentPostId ) {\n\t\t\treturn urlQueryArgs;\n\t\t}\n\t\treturn {\n\t\t\tpost_id: currentPostId,\n\t\t\t...urlQueryArgs,\n\t\t};\n\t}, [ currentPostId, urlQueryArgs ] );\n\n\treturn <ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />;\n}\n"], "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAMO;AACP,kBAA4B;AAC5B,wBAAqC;AACrC,kBAA0B;AAK1B,kBAAoC;AAMlC;AAJF,IAAM,eAAe,CAAC;AAEtB,SAAS,gCAAiC,EAAE,UAAU,GAAI;AACzD,SACC,4CAAC,iCAAY,WACV,8BAAI,0BAA2B,GAClC;AAEF;AAEA,SAAS,gCAAiC,EAAE,SAAS,UAAU,GAAI;AAClE,QAAM,mBAAe;AAAA;AAAA,QAEpB,gBAAI,yBAA0B;AAAA,IAC9B;AAAA,EACD;AACA,SAAO,4CAAC,iCAAY,WAA0B,wBAAc;AAC7D;AAEA,SAAS,kCAAmC,EAAE,SAAS,GAAI;AAC1D,QAAM,CAAE,YAAY,aAAc,QAAI,yBAAU,KAAM;AAEtD,gCAAW,MAAM;AAEhB,UAAM,UAAU,WAAY,MAAM;AACjC,oBAAe,IAAK;AAAA,IACrB,GAAG,GAAK;AACR,WAAO,MAAM,aAAc,OAAQ;AAAA,EACpC,GAAG,CAAC,CAAE;AAEN,SACC,6CAAC,SAAI,OAAQ,EAAE,UAAU,WAAW,GACjC;AAAA,kBACD;AAAA,MAAC;AAAA;AAAA,QACA,OAAQ;AAAA,UACP,UAAU;AAAA,UACV,KAAK;AAAA,UACL,MAAM;AAAA,UACN,WAAW;AAAA,UACX,YAAY;AAAA,QACb;AAAA,QAEA,sDAAC,6BAAQ;AAAA;AAAA,IACV;AAAA,IAED,4CAAC,SAAI,OAAQ,EAAE,SAAS,aAAa,QAAQ,EAAE,GAC5C,UACH;AAAA,KACD;AAEF;AAEO,SAAS,iBAAkB,OAAQ;AACzC,QAAM,qBAAiB,uBAAQ,EAAG;AAClC,QAAM;AAAA,IACL;AAAA,IACA,2BAA2B;AAAA,IAC3B,2BAA2B;AAAA,IAC3B,6BAA6B;AAAA,IAC7B,GAAG;AAAA,EACJ,IAAI;AAEJ,QAAM,EAAE,SAAS,QAAQ,MAAM,QAAI,iCAAqB,SAAU;AAGlE,gCAAW,MAAM;AAChB,QAAK,SAAU;AACd,qBAAe,UAAU;AAAA,IAC1B;AAAA,EACD,GAAG,CAAE,OAAQ,CAAE;AAEf,MAAK,WAAW,WAAY;AAC3B,WACC,4CAAC,8BAA6B,GAAG,OAC9B,WAAC,CAAE,eAAe,WACnB,4CAAC,0BAAQ,WACN,yBAAe,SAClB,GAEF;AAAA,EAEF;AAEA,MAAK,WAAW,aAAa,CAAE,SAAU;AACxC,WAAO,4CAAC,4BAA2B,GAAG,OAAQ;AAAA,EAC/C;AAEA,MAAK,WAAW,SAAU;AACzB,WAAO,4CAAC,4BAAyB,SAAU,OAAU,GAAG,OAAQ;AAAA,EACjE;AAEA,SAAO,4CAAC,0BAAQ,WAA0B,mBAAS;AACpD;AAuCO,SAAS,2BAA4B;AAAA,EAC3C,eAAe;AAAA,EACf,GAAG;AACJ,GAAI;AACH,QAAM,oBAAgB,uBAAW,CAAE,WAAY;AAI9C,UAAM,SAAS,OAAQ,aAAc,GAAG,iBAAiB;AAMzD,WAAO,UAAU,OAAO,WAAW,WAAW,SAAS;AAAA,EACxD,GAAG,CAAC,CAAE;AAEN,QAAM,sBAAkB,wBAAS,MAAM;AACtC,QAAK,CAAE,eAAgB;AACtB,aAAO;AAAA,IACR;AACA,WAAO;AAAA,MACN,SAAS;AAAA,MACT,GAAG;AAAA,IACJ;AAAA,EACD,GAAG,CAAE,eAAe,YAAa,CAAE;AAEnC,SAAO,4CAAC,oBAAiB,cAAe,iBAAoB,GAAG,OAAQ;AACxE;", "names": [] }