Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-to-print

Package Overview
Dependencies
Maintainers
2
Versions
94
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-to-print - npm Package Compare versions

Comparing version 2.15.1 to 3.0.0-beta-1

lib/types/ContentNode.d.ts

8

lib/hooks/useReactToPrint.d.ts

@@ -1,5 +0,3 @@

import * as React from "react";
import type { IReactToPrintProps } from "../types/reactToPrintProps";
type UseReactToPrintHookReturn = (event?: unknown, content?: (() => React.ReactInstance | null)) => void;
export declare const useReactToPrint: (props: IReactToPrintProps) => UseReactToPrintHookReturn;
export {};
import type { UseReactToPrintOptions } from "../types/UseReactToPrintOptions";
import { UseReactToPrintFn } from "../types/UseReactToPrintFn";
export declare function useReactToPrint(options: UseReactToPrintOptions): UseReactToPrintFn;

@@ -1,7 +0,3 @@

export type { IPrintContextProps } from "./components/PrintContext";
export { PrintContextConsumer } from "./components/PrintContext";
export { ReactToPrint } from "./components/ReactToPrint";
export { useReactToPrint } from "./hooks/useReactToPrint";
export type { IReactToPrintProps, ITriggerProps } from "./types/reactToPrintProps";
import { ReactToPrint } from "./components/ReactToPrint";
export default ReactToPrint;
export type { UseReactToPrintFn } from "./types/UseReactToPrintFn";
export type { UseReactToPrintOptions } from "./types/UseReactToPrintOptions";

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("react-dom")):"function"==typeof define&&define.amd?define("lib",["react","react-dom"],t):"object"==typeof exports?exports.lib=t(require("react"),require("react-dom")):e.lib=t(e.react,e["react-dom"])}("undefined"!=typeof self?self:this,(function(e,t){return function(){"use strict";var r={328:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.PrintContextConsumer=t.PrintContext=void 0;var n=r(496),o=Object.prototype.hasOwnProperty.call(n,"createContext");t.PrintContext=o?n.createContext({}):null,t.PrintContextConsumer=t.PrintContext?t.PrintContext.Consumer:function(){return null}},428:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.ReactToPrint=void 0;var n=r(316),o=r(496),i=r(190),a=r(328),c=r(940),s=function(e){function t(){var t=e.apply(this,n.__spreadArray([],n.__read(arguments),!1))||this;return t.startPrint=function(e){var r=t.props,n=r.onAfterPrint,o=r.onPrintError,i=r.print,a=r.documentTitle;setTimeout((function(){var r,c;if(e.contentWindow)if(e.contentWindow.focus(),i)i(e).then((function(){return null==n?void 0:n()})).then((function(){return t.handleRemoveIframe()})).catch((function(e){o?o("print",e):t.logMessages(["An error was thrown by the specified `print` function"])}));else{if(e.contentWindow.print){var s=null!==(c=null===(r=e.contentDocument)||void 0===r?void 0:r.title)&&void 0!==c?c:"",u=e.ownerDocument.title;a&&(e.ownerDocument.title=a,e.contentDocument&&(e.contentDocument.title=a)),e.contentWindow.print(),a&&(e.ownerDocument.title=u,e.contentDocument&&(e.contentDocument.title=s))}else t.logMessages(["Printing for this browser is not currently possible: the browser does not have a `print` method available for iframes."]);null==n||n(),t.handleRemoveIframe()}else t.logMessages(["Printing failed because the `contentWindow` of the print iframe did not load. This is possibly an error with `react-to-print`. Please file an issue: https://github.com/gregnb/react-to-print/issues/"])}),500)},t.triggerPrint=function(e){var r=t.props,n=r.onBeforePrint,o=r.onPrintError;if(n){var i=n();i&&"function"==typeof i.then?i.then((function(){t.startPrint(e)})).catch((function(e){o&&o("onBeforePrint",e)})):t.startPrint(e)}else t.startPrint(e)},t.handlePrint=function(e){var r=t.props,o=r.bodyClass,a=r.content,c=r.copyStyles,s=r.fonts,u=r.pageStyle,l=r.nonce,f="function"==typeof e?e():null;if(f&&"function"==typeof a&&t.logMessages(['"react-to-print" received a `content` prop and a content param passed the callback return by `useReactToPrint. The `content` prop will be ignored.'],"warning"),f||"function"!=typeof a||(f=a()),void 0!==f)if(null!==f){var d=document.createElement("iframe");d.width="".concat(document.documentElement.clientWidth,"px"),d.height="".concat(document.documentElement.clientHeight,"px"),d.style.position="absolute",d.style.top="-".concat(document.documentElement.clientHeight+100,"px"),d.style.left="-".concat(document.documentElement.clientWidth+100,"px"),d.id="printWindow",d.srcdoc="<!DOCTYPE html>";var p=(0,i.findDOMNode)(f);if(p){var h=p.cloneNode(!0),y=h instanceof Text,b=document.querySelectorAll("link[rel~='stylesheet'], link[as='style']"),v=y?[]:h.querySelectorAll("img"),g=y?[]:h.querySelectorAll("video"),m=s?s.length:0;t.numResourcesToLoad=b.length+v.length+g.length+m,t.resourcesLoaded=[],t.resourcesErrored=[];var _=function(e,r){t.resourcesLoaded.includes(e)?t.logMessages(["Tried to mark a resource that has already been handled",e],"debug"):(r?(t.logMessages(n.__spreadArray(['"react-to-print" was unable to load a resource but will continue attempting to print the page'],n.__read(r),!1)),t.resourcesErrored.push(e)):t.resourcesLoaded.push(e),t.resourcesLoaded.length+t.resourcesErrored.length===t.numResourcesToLoad&&t.triggerPrint(d))};d.onload=function(){var e,r,i,a;d.onload=null;var f=d.contentDocument||(null===(r=d.contentWindow)||void 0===r?void 0:r.document);if(f){f.body.appendChild(h),s&&((null===(i=d.contentDocument)||void 0===i?void 0:i.fonts)&&(null===(a=d.contentWindow)||void 0===a?void 0:a.FontFace)?s.forEach((function(e){var t=new FontFace(e.family,e.source,{weight:e.weight,style:e.style});d.contentDocument.fonts.add(t),t.loaded.then((function(){_(t)})).catch((function(e){_(t,["Failed loading the font:",t,"Load error:",e])}))})):(s.forEach((function(e){return _(e)})),t.logMessages(['"react-to-print" is not able to load custom fonts because the browser does not support the FontFace API but will continue attempting to print the page'])));var b="function"==typeof u?u():u;if("string"!=typeof b)t.logMessages(['"react-to-print" expected a "string" from `pageStyle` but received "'.concat(typeof b,'". Styles from `pageStyle` will not be applied.')]);else{var m=f.createElement("style");l&&(m.setAttribute("nonce",l),f.head.setAttribute("nonce",l)),m.appendChild(f.createTextNode(b)),f.head.appendChild(m)}if(o&&(e=f.body.classList).add.apply(e,n.__spreadArray([],n.__read(o.split(" ")),!1)),!y){for(var w=y?[]:p.querySelectorAll("canvas"),P=f.querySelectorAll("canvas"),O=0;O<w.length;++O){var x=w[O],S=P[O].getContext("2d");S&&S.drawImage(x,0,0)}var E=function(e){var t=v[e],r=t.getAttribute("src");if(r){var n=new Image;n.onload=function(){return _(t)},n.onerror=function(e,r,n,o,i){return _(t,["Error loading <img>",t,"Error",i])},n.src=r}else _(t,['Found an <img> tag with an empty "src" attribute. This prevents pre-loading it. The <img> is:',t])};for(O=0;O<v.length;O++)E(O);var T=function(e){var t=g[e];t.preload="auto";var r=t.getAttribute("poster");if(r){var n=new Image;n.onload=function(){return _(t)},n.onerror=function(e,n,o,i,a){return _(t,["Error loading video poster",r,"for video",t,"Error:",a])},n.src=r}else t.readyState>=2?_(t):(t.onloadeddata=function(){return _(t)},t.onerror=function(e,r,n,o,i){return _(t,["Error loading video",t,"Error",i])},t.onstalled=function(){return _(t,["Loading video stalled, skipping",t])})};for(O=0;O<g.length;O++)T(O);var j="input",C=p.querySelectorAll(j),A=f.querySelectorAll(j);for(O=0;O<C.length;O++)A[O].value=C[O].value;var k="input[type=checkbox],input[type=radio]",R=p.querySelectorAll(k),M=f.querySelectorAll(k);for(O=0;O<R.length;O++)M[O].checked=R[O].checked;var D="select",I=p.querySelectorAll(D),q=f.querySelectorAll(D);for(O=0;O<I.length;O++)q[O].value=I[O].value}if(c)for(var F=document.querySelectorAll("style, link[rel~='stylesheet'], link[as='style']"),W=function(e,r){var n=F[e];if("style"===n.tagName.toLowerCase()){var o=f.createElement(n.tagName),i=n.sheet;if(i){var a="";try{for(var c=i.cssRules.length,s=0;s<c;++s)"string"==typeof i.cssRules[s].cssText&&(a+="".concat(i.cssRules[s].cssText,"\r\n"))}catch(e){t.logMessages(["A stylesheet could not be accessed. This is likely due to the stylesheet having cross-origin imports, and many browsers block script access to cross-origin stylesheets. See https://github.com/gregnb/react-to-print/issues/429 for details. You may be able to load the sheet by both marking the stylesheet with the cross `crossorigin` attribute, and setting the `Access-Control-Allow-Origin` header on the server serving the stylesheet. Alternatively, host the stylesheet on your domain to avoid this issue entirely.",n],"warning")}o.setAttribute("id","react-to-print-".concat(e)),l&&o.setAttribute("nonce",l),o.appendChild(f.createTextNode(a)),f.head.appendChild(o)}}else if(n.getAttribute("href"))if(n.hasAttribute("disabled"))t.logMessages(["`react-to-print` encountered a <link> tag with a `disabled` attribute and will ignore it. Note that the `disabled` attribute is deprecated, and some browsers ignore it. You should stop using it. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-disabled. The <link> is:",n],"warning"),_(n);else{for(var u=f.createElement(n.tagName),d=(s=0,n.attributes.length);s<d;++s){var p=n.attributes[s];p&&u.setAttribute(p.nodeName,p.nodeValue||"")}u.onload=function(){return _(u)},u.onerror=function(e,t,r,n,o){return _(u,["Failed to load",u,"Error:",o])},l&&u.setAttribute("nonce",l),f.head.appendChild(u)}else t.logMessages(["`react-to-print` encountered a <link> tag with an empty `href` attribute. In addition to being invalid HTML, this can cause problems in many browsers, and so the <link> was not loaded. The <link> is:",n],"warning"),_(n)},L=(O=0,F.length);O<L;++O)W(O)}0!==t.numResourcesToLoad&&c||t.triggerPrint(d)},t.handleRemoveIframe(!0),document.body.appendChild(d)}else t.logMessages(['"react-to-print" could not locate the DOM node corresponding with the `content` prop'])}else t.logMessages(['There is nothing to print because the "content" prop returned "null". Please ensure "content" is renderable before allowing "react-to-print" to be called.']);else t.logMessages(["To print a functional component ensure it is wrapped with `React.forwardRef`, and ensure the forwarded ref is used. See the README for an example: https://github.com/gregnb/react-to-print#examples"])},t.handleRemoveIframe=function(e){var r=t.props.removeAfterPrint;if(e||r){var n=document.getElementById("printWindow");n&&document.body.removeChild(n)}},t.logMessages=function(e,r){void 0===r&&(r="error"),t.props.suppressErrors||("error"===r?console.error(e):"warning"===r?console.warn(e):"debug"===r&&console.debug(e))},t}return n.__extends(t,e),t.prototype.handleClick=function(e,t){var r=this,n=this.props,o=n.onBeforeGetContent,i=n.onPrintError;if(o){var a=o();a&&"function"==typeof a.then?a.then((function(){return r.handlePrint(t)})).catch((function(e){i&&i("onBeforeGetContent",e)})):this.handlePrint(t)}else this.handlePrint(t)},t.prototype.render=function(){var e=this.props,t=e.children,r=e.trigger;if(r)return o.cloneElement(r(),{onClick:this.handleClick.bind(this)});if(!a.PrintContext)return this.logMessages(['"react-to-print" requires React ^16.3.0 to be able to use "PrintContext"']),null;var n={handlePrint:this.handleClick.bind(this)};return o.createElement(a.PrintContext.Provider,{value:n},t)},t.defaultProps=c.defaultProps,t}(o.Component);t.ReactToPrint=s},940:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.defaultProps=void 0,t.defaultProps={copyStyles:!0,pageStyle:"\n @page {\n /* Remove browser default header (title) and footer (url) */\n margin: 0;\n }\n @media print {\n body {\n /* Tell browsers to print background colors */\n -webkit-print-color-adjust: exact; /* Chrome/Safari/Edge/Opera */\n color-adjust: exact; /* Firefox */\n }\n }\n ",removeAfterPrint:!1,suppressErrors:!1}},892:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.useReactToPrint=void 0;var n=r(316),o=r(496),i=r(428),a=r(940),c=r(860),s=Object.prototype.hasOwnProperty.call(o,"useMemo")&&Object.prototype.hasOwnProperty.call(o,"useCallback");t.useReactToPrint=function(e){if(!s)return e.suppressErrors||console.error('"react-to-print" requires React ^16.8.0 to be able to use "useReactToPrint"'),function(){throw new Error('"react-to-print" requires React ^16.8.0 to be able to use "useReactToPrint"')};var t=o.useMemo((function(){return new i.ReactToPrint(n.__assign(n.__assign({},a.defaultProps),e))}),[e]);return o.useCallback((function(e,r){return(0,c.wrapCallbackWithArgs)(t,t.handleClick,r)(e)}),[t])}},860:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.wrapCallbackWithArgs=void 0;var n=r(316);t.wrapCallbackWithArgs=function(e,t){for(var r=[],o=2;o<arguments.length;o++)r[o-2]=arguments[o];return function(){for(var o=[],i=0;i<arguments.length;i++)o[i]=arguments[i];return t.apply(e,n.__spreadArray(n.__spreadArray([],n.__read(o),!1),n.__read(r),!1))}}},496:function(t){t.exports=e},190:function(e){e.exports=t},316:function(e,t,r){r.r(t),r.d(t,{__addDisposableResource:function(){return D},__assign:function(){return i},__asyncDelegator:function(){return S},__asyncGenerator:function(){return x},__asyncValues:function(){return E},__await:function(){return O},__awaiter:function(){return h},__classPrivateFieldGet:function(){return k},__classPrivateFieldIn:function(){return M},__classPrivateFieldSet:function(){return R},__createBinding:function(){return b},__decorate:function(){return c},__disposeResources:function(){return q},__esDecorate:function(){return u},__exportStar:function(){return v},__extends:function(){return o},__generator:function(){return y},__importDefault:function(){return A},__importStar:function(){return C},__makeTemplateObject:function(){return T},__metadata:function(){return p},__param:function(){return s},__propKey:function(){return f},__read:function(){return m},__rest:function(){return a},__runInitializers:function(){return l},__setFunctionName:function(){return d},__spread:function(){return _},__spreadArray:function(){return P},__spreadArrays:function(){return w},__values:function(){return g}});var n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)};function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var i=function(){return i=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var o in t=arguments[r])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},i.apply(this,arguments)};function a(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]])}return r}function c(e,t,r,n){var o,i=arguments.length,a=i<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,r,n);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(a=(i<3?o(a):i>3?o(t,r,a):o(t,r))||a);return i>3&&a&&Object.defineProperty(t,r,a),a}function s(e,t){return function(r,n){t(r,n,e)}}function u(e,t,r,n,o,i){function a(e){if(void 0!==e&&"function"!=typeof e)throw new TypeError("Function expected");return e}for(var c,s=n.kind,u="getter"===s?"get":"setter"===s?"set":"value",l=!t&&e?n.static?e:e.prototype:null,f=t||(l?Object.getOwnPropertyDescriptor(l,n.name):{}),d=!1,p=r.length-1;p>=0;p--){var h={};for(var y in n)h[y]="access"===y?{}:n[y];for(var y in n.access)h.access[y]=n.access[y];h.addInitializer=function(e){if(d)throw new TypeError("Cannot add initializers after decoration has completed");i.push(a(e||null))};var b=(0,r[p])("accessor"===s?{get:f.get,set:f.set}:f[u],h);if("accessor"===s){if(void 0===b)continue;if(null===b||"object"!=typeof b)throw new TypeError("Object expected");(c=a(b.get))&&(f.get=c),(c=a(b.set))&&(f.set=c),(c=a(b.init))&&o.unshift(c)}else(c=a(b))&&("field"===s?o.unshift(c):f[u]=c)}l&&Object.defineProperty(l,n.name,f),d=!0}function l(e,t,r){for(var n=arguments.length>2,o=0;o<t.length;o++)r=n?t[o].call(e,r):t[o].call(e);return n?r:void 0}function f(e){return"symbol"==typeof e?e:"".concat(e)}function d(e,t,r){return"symbol"==typeof t&&(t=t.description?"[".concat(t.description,"]"):""),Object.defineProperty(e,"name",{configurable:!0,value:r?"".concat(r," ",t):t})}function p(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function h(e,t,r,n){return new(r||(r=Promise))((function(o,i){function a(e){try{s(n.next(e))}catch(e){i(e)}}function c(e){try{s(n.throw(e))}catch(e){i(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(a,c)}s((n=n.apply(e,t||[])).next())}))}function y(e,t){var r,n,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(s){return function(c){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&c[0]?n.return:c[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,c[1])).done)return o;switch(n=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,n=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(e){c=[6,e],n=0}finally{r=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,s])}}}var b=Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]};function v(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||b(t,e,r)}function g(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function m(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,i=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}return a}function _(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(m(arguments[t]));return e}function w(){for(var e=0,t=0,r=arguments.length;t<r;t++)e+=arguments[t].length;var n=Array(e),o=0;for(t=0;t<r;t++)for(var i=arguments[t],a=0,c=i.length;a<c;a++,o++)n[o]=i[a];return n}function P(e,t,r){if(r||2===arguments.length)for(var n,o=0,i=t.length;o<i;o++)!n&&o in t||(n||(n=Array.prototype.slice.call(t,0,o)),n[o]=t[o]);return e.concat(n||Array.prototype.slice.call(t))}function O(e){return this instanceof O?(this.v=e,this):new O(e)}function x(e,t,r){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n,o=r.apply(e,t||[]),i=[];return n={},a("next"),a("throw"),a("return"),n[Symbol.asyncIterator]=function(){return this},n;function a(e){o[e]&&(n[e]=function(t){return new Promise((function(r,n){i.push([e,t,r,n])>1||c(e,t)}))})}function c(e,t){try{(r=o[e](t)).value instanceof O?Promise.resolve(r.value.v).then(s,u):l(i[0][2],r)}catch(e){l(i[0][3],e)}var r}function s(e){c("next",e)}function u(e){c("throw",e)}function l(e,t){e(t),i.shift(),i.length&&c(i[0][0],i[0][1])}}function S(e){var t,r;return t={},n("next"),n("throw",(function(e){throw e})),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,o){t[n]=e[n]?function(t){return(r=!r)?{value:O(e[n](t)),done:!1}:o?o(t):t}:o}}function E(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=g(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise((function(n,o){!function(e,t,r,n){Promise.resolve(n).then((function(t){e({value:t,done:r})}),t)}(n,o,(t=e[r](t)).done,t.value)}))}}}function T(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var j=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t};function C(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&b(t,e,r);return j(t,e),t}function A(e){return e&&e.__esModule?e:{default:e}}function k(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function R(e,t,r,n,o){if("m"===n)throw new TypeError("Private method is not writable");if("a"===n&&!o)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===n?o.call(e,r):o?o.value=r:t.set(e,r),r}function M(e,t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Cannot use 'in' operator on non-object");return"function"==typeof e?t===e:e.has(t)}function D(e,t,r){if(null!=t){if("object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object expected.");var n;if(r){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");n=t[Symbol.asyncDispose]}if(void 0===n){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");n=t[Symbol.dispose]}if("function"!=typeof n)throw new TypeError("Object not disposable.");e.stack.push({value:t,dispose:n,async:r})}else r&&e.stack.push({async:!0});return t}var I="function"==typeof SuppressedError?SuppressedError:function(e,t,r){var n=new Error(r);return n.name="SuppressedError",n.error=e,n.suppressed=t,n};function q(e){function t(t){e.error=e.hasError?new I(t,e.error,"An error was suppressed during disposal."):t,e.hasError=!0}return function r(){for(;e.stack.length;){var n=e.stack.pop();try{var o=n.dispose&&n.dispose.call(n.value);if(n.async)return Promise.resolve(o).then(r,(function(e){return t(e),r()}))}catch(e){t(e)}}if(e.hasError)throw e.error}()}t.default={__extends:o,__assign:i,__rest:a,__decorate:c,__param:s,__metadata:p,__awaiter:h,__generator:y,__createBinding:b,__exportStar:v,__values:g,__read:m,__spread:_,__spreadArrays:w,__spreadArray:P,__await:O,__asyncGenerator:x,__asyncDelegator:S,__asyncValues:E,__makeTemplateObject:T,__importStar:C,__importDefault:A,__classPrivateFieldGet:k,__classPrivateFieldSet:R,__classPrivateFieldIn:M,__addDisposableResource:D,__disposeResources:q}}},n={};function o(e){var t=n[e];if(void 0!==t)return t.exports;var i=n[e]={exports:{}};return r[e](i,i.exports,o),i.exports}o.d=function(e,t){for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return function(){var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.useReactToPrint=e.ReactToPrint=e.PrintContextConsumer=void 0;var t=o(328);Object.defineProperty(e,"PrintContextConsumer",{enumerable:!0,get:function(){return t.PrintContextConsumer}});var r=o(428);Object.defineProperty(e,"ReactToPrint",{enumerable:!0,get:function(){return r.ReactToPrint}});var n=o(892);Object.defineProperty(e,"useReactToPrint",{enumerable:!0,get:function(){return n.useReactToPrint}});var a=o(428);e.default=a.ReactToPrint}(),i}()}));
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define("lib",["react"],t):"object"==typeof exports?exports.lib=t(require("react")):e.lib=t(e.react)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={496:function(t){t.exports=e}},o={};function n(e){var r=o[e];if(void 0!==r)return r.exports;var s=o[e]={exports:{}};return t[e](s,s.exports,n),s.exports}n.d=function(e,t){for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var r={};return function(){n.r(r),n.d(r,{useReactToPrint:function(){return l}});var e=n(496);function t({level:e="error",messages:t,suppressErrors:o=!1}){o||("error"===e?console.error(t):"warning"===e?console.warn(t):"debug"===e&&console.debug(t))}function o(e,t){if(t||!e){const e=document.getElementById("printWindow");e&&document.body.removeChild(e)}}function s(e,n){const{documentTitle:r,onAfterPrint:s,onPrintError:i,preserveAfterPrint:l,print:a,suppressErrors:c}=n;setTimeout((()=>{var n,d;if(e.contentWindow)if(e.contentWindow.focus(),a)a(e).then((()=>null==s?void 0:s())).then((()=>o(l))).catch((e=>{i?i("print",e):t({messages:["An error was thrown by the specified `print` function"],suppressErrors:c})}));else{if(e.contentWindow.print){const t=null!==(d=null===(n=e.contentDocument)||void 0===n?void 0:n.title)&&void 0!==d?d:"",o=e.ownerDocument.title;r&&(e.ownerDocument.title=r,e.contentDocument&&(e.contentDocument.title=r)),e.contentWindow.print(),r&&(e.ownerDocument.title=o,e.contentDocument&&(e.contentDocument.title=t))}else t({messages:["Printing for this browser is not currently possible: the browser does not have a `print` method available for iframes."],suppressErrors:c});null==s||s(),o(l)}else t({messages:["Printing failed because the `contentWindow` of the print iframe did not load. This is possibly an error with `react-to-print`. Please file an issue: https://github.com/MatthewHerbst/react-to-print/issues/"],suppressErrors:c})}),500)}const i='\n @page {\n /* Remove browser default header (title) and footer (url) */\n margin: 0;\n }\n @media print {\n body {\n /* Tell browsers to print background colors */\n color-adjust: exact; /* Firefox. This is an older version of "print-color-adjust" */\n print-color-adjust: exact; /* Firefox/Safari */\n -webkit-print-color-adjust: exact; /* Chrome/Safari/Edge/Opera */\n }\n }\n';function l(n){const{contentRef:r,fonts:l,ignoreGlobalStyles:a,preserveAfterPrint:c,suppressErrors:d}=n,u=(0,e.useCallback)((e=>{o(c,!0);const u=function({contentRef:e,optionalContent:o,suppressErrors:n}){return o?(e&&t({level:"warning",messages:['"react-to-print" received a `contentRef` option and a optional-content param passed to its callback. The `contentRef` option will be ignored.']}),o()):e?e.current:void t({messages:['"react-to-print" did not receive a `contentRef` option or a optional-content param pass to its callback.'],suppressErrors:n})}({contentRef:r,optionalContent:e,suppressErrors:d});if(!u)return void t({messages:["There is nothing to print"],suppressErrors:d});if(!u)return void t({messages:['"react-to-print" could not locate the DOM node corresponding with the `content` prop'],suppressErrors:d});const p=u.cloneNode(!0),h=document.querySelectorAll("link[rel~='stylesheet'], link[as='style']"),m=p.querySelectorAll("img"),g=p.querySelectorAll("video"),f=l?l.length:0,b=(a?0:h.length)+m.length+g.length+f,y=[],v=[],w=function(){const e=document.createElement("iframe");return e.width=`${document.documentElement.clientWidth}px`,e.height=`${document.documentElement.clientHeight}px`,e.style.position="absolute",e.style.top=`-${document.documentElement.clientHeight+100}px`,e.style.left=`-${document.documentElement.clientWidth+100}px`,e.id="printWindow",e.srcdoc="<!DOCTYPE html>",e}(),E=(e,o)=>{y.includes(e)?t({level:"debug",messages:["Tried to mark a resource that has already been handled",e],suppressErrors:d}):(o?(t({messages:['"react-to-print" was unable to load a resource but will continue attempting to print the page',...o],suppressErrors:d}),v.push(e)):y.push(e),y.length+v.length===b&&function(e,t){const{onBeforePrint:o,onPrintError:n}=t;o?o().then((()=>{s(e,t)})).catch((e=>{null==n||n("onBeforePrint",e)})):s(e,t)}(w,n))};w.onload=()=>function(e,o,n,r){var l,a,c;const{clonedContentNode:d,contentNode:u,numResourcesToLoad:p,renderComponentImgNodes:h,renderComponentVideoNodes:m}=n,{bodyClass:g,fonts:f,ignoreGlobalStyles:b,pageStyle:y,nonce:v,suppressErrors:w}=r;e.onload=null;const E=e.contentDocument||(null===(l=e.contentWindow)||void 0===l?void 0:l.document);if(E){E.body.appendChild(d),f&&((null===(a=e.contentDocument)||void 0===a?void 0:a.fonts)&&(null===(c=e.contentWindow)||void 0===c?void 0:c.FontFace)?f.forEach((t=>{const n=new FontFace(t.family,t.source,{weight:t.weight,style:t.style});e.contentDocument.fonts.add(n),n.loaded.then((()=>{o(n)})).catch((e=>{o(n,["Failed loading the font:",n,"Load error:",e])}))})):(f.forEach((e=>o(e))),t({messages:['"react-to-print" is not able to load custom fonts because the browser does not support the FontFace API but will continue attempting to print the page'],suppressErrors:w})));const n=null!=y?y:i,r=E.createElement("style");v&&(r.setAttribute("nonce",v),E.head.setAttribute("nonce",v)),r.appendChild(E.createTextNode(n)),E.head.appendChild(r),g&&E.body.classList.add(...g.split(" "));const s=u.querySelectorAll("canvas"),l=E.querySelectorAll("canvas");for(let e=0;e<s.length;++e){const t=s[e],o=l[e].getContext("2d");o&&o.drawImage(t,0,0)}for(let e=0;e<h.length;e++){const t=h[e],n=t.getAttribute("src");if(n){const e=new Image;e.onload=()=>o(t),e.onerror=(e,n,r,s,i)=>o(t,["Error loading <img>",t,"Error",i]),e.src=n}else o(t,['Found an <img> tag with an empty "src" attribute. This prevents pre-loading it. The <img> is:',t])}for(let e=0;e<m.length;e++){const t=m[e];t.preload="auto";const n=t.getAttribute("poster");if(n){const e=new Image;e.onload=()=>o(t),e.onerror=(e,r,s,i,l)=>o(t,["Error loading video poster",n,"for video",t,"Error:",l]),e.src=n}else t.readyState>=2?o(t):(t.onloadeddata=()=>o(t),t.onerror=(e,n,r,s,i)=>o(t,["Error loading video",t,"Error",i]),t.onstalled=()=>o(t,["Loading video stalled, skipping",t]))}const p="input",A=u.querySelectorAll(p),S=E.querySelectorAll(p);for(let e=0;e<A.length;e++)S[e].value=A[e].value;const T="input[type=checkbox],input[type=radio]",x=u.querySelectorAll(T),k=E.querySelectorAll(T);for(let e=0;e<x.length;e++)k[e].checked=x[e].checked;const C="select",P=u.querySelectorAll(C),N=E.querySelectorAll(C);for(let e=0;e<P.length;e++)N[e].value=P[e].value;if(!b){const e=document.querySelectorAll("style, link[rel~='stylesheet'], link[as='style']");for(let n=0,r=e.length;n<r;++n){const r=e[n];if("style"===r.tagName.toLowerCase()){const e=E.createElement(r.tagName),o=r.sheet;if(o){let s="";try{const e=o.cssRules.length;for(let t=0;t<e;++t)"string"==typeof o.cssRules[t].cssText&&(s+=`${o.cssRules[t].cssText}\r\n`)}catch(e){t({messages:["A stylesheet could not be accessed. This is likely due to the stylesheet having cross-origin imports, and many browsers block script access to cross-origin stylesheets. See https://github.com/MatthewHerbst/react-to-print/issues/429 for details. You may be able to load the sheet by both marking the stylesheet with the cross `crossorigin` attribute, and setting the `Access-Control-Allow-Origin` header on the server serving the stylesheet. Alternatively, host the stylesheet on your domain to avoid this issue entirely.",r],level:"warning"})}e.setAttribute("id",`react-to-print-${n}`),v&&e.setAttribute("nonce",v),e.appendChild(E.createTextNode(s)),E.head.appendChild(e)}}else if(r.getAttribute("href"))if(r.hasAttribute("disabled"))t({messages:["`react-to-print` encountered a <link> tag with a `disabled` attribute and will ignore it. Note that the `disabled` attribute is deprecated, and some browsers ignore it. You should stop using it. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-disabled. The <link> is:",r],level:"warning"}),o(r);else{const e=E.createElement(r.tagName);for(let t=0,o=r.attributes.length;t<o;++t){const o=r.attributes[t];o&&e.setAttribute(o.nodeName,o.nodeValue||"")}e.onload=()=>o(e),e.onerror=(t,n,r,s,i)=>o(e,["Failed to load",e,"Error:",i]),v&&e.setAttribute("nonce",v),E.head.appendChild(e)}else t({messages:["`react-to-print` encountered a <link> tag with an empty `href` attribute. In addition to being invalid HTML, this can cause problems in many browsers, and so the <link> was not loaded. The <link> is:",r],level:"warning"}),o(r)}}}0===p&&s(e,r)}(w,E,{clonedContentNode:p,contentNode:u,numResourcesToLoad:b,renderComponentImgNodes:m,renderComponentVideoNodes:g},n),document.body.appendChild(w)}),[n]);return u}}(),r}()}));
{
"name": "react-to-print",
"version": "2.15.1",
"version": "3.0.0-beta-1",
"description": "Print React components in the browser",

@@ -18,3 +18,3 @@ "main": "lib/index.js",

"type": "git",
"url": "git+https://github.com/gregnb/react-to-print.git"
"url": "git+https://github.com/MatthewHerbst/react-to-print.git"
},

@@ -33,12 +33,11 @@ "keywords": [

"bugs": {
"url": "https://github.com/gregnb/react-to-print/issues"
"url": "https://github.com/MatthewHerbst/react-to-print/issues"
},
"homepage": "https://github.com/gregnb/react-to-print#readme",
"homepage": "https://github.com/MatthewHerbst/react-to-print#readme",
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19"
},
"devDependencies": {
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",

@@ -54,4 +53,4 @@ "@typescript-eslint/parser": "^6.21.0",

"lint-staged": "^15.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-tabs": "^6.0.2",

@@ -61,3 +60,3 @@ "style-loader": "^3.3.4",

"tslib": "^2.6.2",
"typescript": "^5.3.3",
"typescript": "^5.5.3",
"url-loader": "^4.1.1",

@@ -64,0 +63,0 @@ "webpack": "^5.90.1",

@@ -10,3 +10,3 @@ <p align="center">

So you've created a React component and would love to give end users the ability to print out the contents of that component. This package aims to solve that by popping up a print window with CSS styles copied over as well.
Print the content of a React component.

@@ -23,41 +23,45 @@ ## Demo

### &lt;ReactToPrint />
### Usage
The component accepts the following props:
```tsx
const contentRef = useRef<HTMLDivElement>(null);
const handlePrint = useReactToPrint({ contentRef });
| Name | Type | Description |
return (
<div>
<button onClick={handlePrint}>Print</button>
<div ref={contentRef}>Content to print</div>
</div>
);
```
### Options
| Option | Type | Description |
| :-------------------: | :------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| **`bodyClass?`** | `string` | One or more class names to pass to the print window, separated by spaces |
| **`content?`** | `function` | A function that returns a component reference value. The content of this reference value is then used for print. Alternatively, pass the content directly to the callback returned by `useReactToPrint` |
| **`copyStyles?`** | `boolean` | Copy all `<style>` and `<link type="stylesheet" />` tags from `<head>` inside the parent window into the print window. (default: `true`) |
| **`documentTitle?`** | `string` | Set the title for printing when saving as a file |
| **`fonts?`** | `{ family: string, source: string; weight?: string; style?: string; }[]` | You may optionally provide a list of fonts which will be loaded into the printing iframe. This is useful if you are using custom fonts |
| **`onAfterPrint?`** | `function` | Callback function that triggers after the print dialog is closed regardless of if the user selected to print or cancel |
| **`onBeforeGetContent?`** | `function` | Callback function that triggers before the library gathers the page's content. Either returns void or a Promise. This can be used to change the content on the page before printing |
| **`onBeforePrint?`** | `function` | Callback function that triggers before print. Either returns void or a Promise. Note: this function is run immediately prior to printing, but after the page's content has been gathered. To modify content before printing, use `onBeforeGetContent` instead |
| **`onPrintError?`** | `function` | Callback function (signature: `function(errorLocation: 'onBeforePrint' \| 'onBeforeGetContent' \| 'print', error: Error)`) that will be called if there is a printing error serious enough that printing cannot continue. Currently limited to Promise rejections in `onBeforeGetContent`, `onBeforePrint`, and `print`. Use this to attempt to print again. `errorLocation` will tell you in which callback the Promise was rejected |
| **`pageStyle?`** | `string` or `function` | We set some basic styles to help improve page printing. Use this to override them and provide your own. If given as a function it must return a `string` |
| **`print?`** | `function` | If passed, this function will be used instead of `window.print` to print the content. This function is passed the `HTMLIFrameElement` which is the iframe used internally to gather content for printing. When finished, this function must return a Promise. Use this to print in non-browser environments such as Electron |
| **`removeAfterPrint?`** | `boolean` | Remove the print iframe after action. Defaults to `false` |
| **`contentRef?`** | `React.RefObject<Element \| Text>` | The ref pointing to the content to be printed. Alternatively, pass the ref directly to the callback returned by `useReactToPrint` |
| **`documentTitle?`** | `string` | Set the title for printing when saving as a file. Ignored when passing a custom `print` option |
| **`fonts?`** | `{ family: string, source: string; weight?: string; style?: string; }[]` | A list of fonts to load into the printing iframe. This is useful if you are using custom fonts |
| **`ignoreGlobalStyles?`** | `boolean` | Ignore all `<style>` and `<link type="stylesheet" />` tags from `<head>` |
| **`nonce?`** | `string` | Set the [`nonce`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) attribute for allow-listing script and style elements for Content Security Policy (CSP) |
| **`onAfterPrint?`** | `() => void` | Callback function that triggers after the print dialog is closed _regardless of if the user selected to print or cancel_ |
| **`onBeforePrint?`** | `() => Promise<void>` | Callback function that triggers before print. This can be used to change the content on the page before printing as an alternative to, or in conjunction with `@media print` queries |
| **`onPrintError?`** | `(errorLocation: 'onBeforePrint' \| 'print', error: Error) => void` | Called if there is a printing error serious enough that printing cannot continue. Currently limited to Promise rejections in `onBeforePrint`, and `print`. Use this to attempt to print again. `errorLocation` will tell you where the Promise was rejected |
| **`pageStyle?`** | `string` | `react-to-print` sets some basic styles to help improve page printing, notably, removing the header and footer that most browsers add. Use this to override these styles and provide your own |
| **`preserveAfterPrint?`** | `boolean` | Preserve the print iframe after printing. This can be useful for debugging by inspecting the print iframe |
| **`print?`** | `(iframe: HTMLIFrameElement) => Promise<void>` | If passed, this function will be used instead of `window.print` to print the content. Use this to print in non-browser environments such as Electron |
| **`suppressErrors?`** | `boolean` | When passed, prevents `console` logging of errors |
| **`trigger?`** | `function` | A function that returns a React Component or Element. Note: under the hood, we inject a custom `onClick` prop into the returned Component/Element. As such, do not provide an `onClick` prop to the root node returned by `trigger`, as it will be overwritten |
| **`nonce?`** | `string` | Set the nonce attribute for whitelisting script and style -elements for CSP (content security policy) |
### `PrintContextConsumer`
The hook returns a function that will initiate the print process when called. This function can also be optionally passed the `content` when called, allowing for its use in conditional rendering logic (where hooks are not allowed) and/or in non-React code such as a util function. See the repo examples for more.
If you need extra control over printing and don't want to specify `trigger` directly, `PrintContextConsumer` allows you to gain direct access to the `handlePrint` method which triggers the print action. Requires React >=16.3.0. See the examples below for usage.
### `useReactToPrint`
For functional components, use the `useReactToPrint` hook, which accepts an object with the same configuration props as `<ReactToPrint />` and returns a `handlePrint` function which when called will trigger the print action. Requires React >=16.8.0. See the examples below for usage. Additionally, for-fine tuned control, the `handlePrint` callback can accept an optional `content` prop which will can be used instead of passing a `content` prop to the hook itself.
## Compatibility
`react-to-print` should be compatible with most major browsers. We also do our best to support IE11.
`react-to-print` should be compatible with most modern browsers.
### Mobile Browsers in WebView
While printing on mobile browsers should work, printing within a WebView (when your page is opened by another app such as Facebook or Slack, but not by the full browser itself) is known to not work on many if not all WebViews. Some don't make the correct API available. Others make it available but cause printing to no-op when in WebView.
While printing on mobile browsers generally works, printing within a WebView (when your page is opened by an app such as Facebook or Slack, but not by the full browser itself) is known to generally not work. Some WebViews don't make the correct API available. Others make it available but cause printing to no-op.
We are actively researching resolutions to this issue, but it likely requires changes by Google/Chromium and Apple/WebKit. See [#384](https://github.com/gregnb/react-to-print/issues/384) for more information. If you know of a way we can solve this, your help would be greatly appreciated.
We are actively researching resolutions to this issue, but it likely requires changes by Google/Chromium and Apple/WebKit. See [#384](https://github.com/MatthewHerbst/react-to-print/issues/384) for more information. If you know of a way we can solve this your help would be greatly appreciated.

@@ -68,145 +72,13 @@ ### Known Incompatible Browsers

## Examples
[![Run react-to-print](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/rzdhd)
```jsx
// Using a class component, everything works without issue
export class ComponentToPrint extends React.PureComponent {
render() {
return (
<div>My cool content here!</div>
);
}
}
// Using a functional component, you must wrap it in React.forwardRef, and then forward the ref to
// the node you want to be the root of the print (usually the outer most node in the ComponentToPrint)
// https://reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components
export const ComponentToPrint = React.forwardRef((props, ref) => {
return (
<div ref={ref}>My cool content here!</div>
);
});
```
### Calling from class components
```jsx
import React from 'react';
import ReactToPrint from 'react-to-print';
import { ComponentToPrint } from './ComponentToPrint';
class Example extends React.PureComponent {
render() {
return (
<div>
<ReactToPrint
trigger={() => {
// NOTE: could just as easily return <SomeComponent />. Do NOT pass an `onClick` prop
// to the root node of the returned component as it will be overwritten.
return <a href="#">Print this out!</a>;
}}
content={() => this.componentRef}
/>
<ComponentToPrint ref={el => (this.componentRef = el)} />
</div>
);
}
}
```
### Calling from class components with `PrintContextConsumer`
```jsx
import React from 'react';
import ReactToPrint, { PrintContextConsumer } from 'react-to-print';
import { ComponentToPrint } from './ComponentToPrint';
class Example extends React.PureComponent {
render() {
return (
<div>
<ReactToPrint content={() => this.componentRef}>
<PrintContextConsumer>
{({ handlePrint }) => (
<button onClick={handlePrint}>Print this out!</button>
)}
</PrintContextConsumer>
</ReactToPrint>
<ComponentToPrint ref={el => (this.componentRef = el)} />
</div>
);
}
}
```
### Calling from functional components with [useReactToPrint](https://reactjs.org/docs/hooks-intro.html)
```jsx
import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';
import { ComponentToPrint } from './ComponentToPrint';
const Example = () => {
const componentRef = useRef();
const handlePrint = useReactToPrint({
content: () => componentRef.current,
});
return (
<div>
<ComponentToPrint ref={componentRef} />
<button onClick={handlePrint}>Print this out!</button>
</div>
);
};
```
### Calling from functional components with [useReactToPrint](https://reactjs.org/docs/hooks-intro.html) using `content` passed to `handlePrint()`
```jsx
import React, { useRef } from 'react';
import { useReactToPrint } from 'react-to-print';
export const AnotherExample = () => {
const contentToPrint = useRef(null);
const handlePrint = useReactToPrint({
documentTitle: "Print This Document",
onBeforePrint: () => console.log("before printing..."),
onAfterPrint: () => console.log("after printing..."),
removeAfterPrint: true,
});
return (
<>
<div ref={contentToPrint}>Hello Again</div>
<button onClick={() => {
handlePrint(null, () => contentToPrint.current);
}}>
PRINT
</button>
</>
)
}
```
**Note ([401](https://github.com/gregnb/react-to-print/issues/401)):** In TypeScript, if you encounter `componentRef.current` error such as: `Type 'undefined' is not assignable to type 'ReactInstance | null'.`, add `null` inside the `useRef()`:
```ts
const componentRef = useRef(null);
```
## Known Issues
- Some mobile browser may, instead of printing, open the native Share action instead
- `onAfterPrint` may fire immediately (before the print dialog is closed) on newer versions of Safari where [`window.print`](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) does not block
- ([401](https://github.com/MatthewHerbst/react-to-print/issues/401)): TypeScript errors such as `Type 'undefined' is not assignable to type 'ReactInstance | null'.`. You likely need to set your ref to initially be `null`: `useRef(null)`
## Common Pitfalls
- `documentTitle` will not work if `react-to-print` is running within an `iframe`. If `react-to-print` is running within an `iframe` and your script has access to the parent document, you may be able to manually set and then restore the parent document's `title` during the print. This can be done by leveraging the `onBeforeGetContent` and `onAfterPrint` props.
- `documentTitle` will not work if `react-to-print` is run within an `iframe`. If `react-to-print` is run within an `iframe` and your script has access to the parent document, you may be able to manually set and then restore the parent document's `title` during the print. This can be done by leveraging the `onBeforePrint` and `onAfterPrint` callbacks.
- When printing, only styles that directly target the printed nodes will be applied, since the parent nodes will not exist in the DOM used for the print. For example, in the code below, if the `<p>` tag is the root of the `ComponentToPrint` then the red styling will *not* be applied. Be sure to target all printed content directly and not from unprinted parents.
- When printing, only styles that directly target the printed nodes will be applied as the parent nodes of the printed nodes will not exist in the print DOM. For example, in the code below, if the `<p>` tag is the root of the `ComponentToPrint` then the red styling will *not* be applied. Be sure to target all printed content directly and not from unprinted parents.

@@ -223,8 +95,6 @@ ```jsx

- The `connect` method from `react-redux` returns a functional component that cannot be assigned a reference to be used within the `content` props' callback in `react-to-print`. To use a component wrapped in `connect` within `content` create an intermediate class component that simply renders your component wrapped in `connect`. See [280](https://github.com/gregnb/react-to-print/issues/280) for more.
- The `connect` method from `react-redux` returns a functional component that cannot be assigned a reference to be used within the `contentRef`. To use a component wrapped in `connect` within `contentRef`, create an intermediate component that simply renders your component wrapped in `connect`. See [280](https://github.com/MatthewHerbst/react-to-print/issues/280) for more.
- Using a custom component as the return for the `trigger` props is possible, just ensure you pass along the `onClick` prop. See [248](https://github.com/gregnb/react-to-print/issues/248) for an example.
- When rendering multiple components to print, ensure each is passed a unique ref. Then, either use a unique `useReactToPrint` call for each component, or, using a single `useReactToPrint` call pass the refs at print-time to the printing function returned by the hook. If you share refs across components only the last component will be printed. See [323](https://github.com/MatthewHerbst/react-to-print/issues/323) for more.
- When rendering multiple components to print, for example, if you have a list of charts and want each chart to have its own print icon, ideally you will wrap each component to print + print button in its own component, and just render a list of those components. However, if you cannot do that for some reason, in your `.map` ensure that each component gets a unique `ref` value passed to it, otherwise printing any of the components will always print the last component. See [323](https://github.com/gregnb/react-to-print/issues/323) for more.
## FAQ

@@ -234,3 +104,3 @@

No. We aren't able to print a PDF as we lose control once the print preview window opens. However, it should be very easy to use `react-to-print` to take the information you need an pass it to a library that can generate a PDF.
No. We aren't able to print a PDF as we lose control once the print preview window opens. However, it should be very easy to use `react-to-print` to take the information you need and pass it to a library that can generate a PDF.

@@ -247,8 +117,36 @@ ```tsx

For examples of how others have done this, see [#484](https://github.com/gregnb/react-to-print/issues/484)
For examples of how others have done this, see [#484](https://github.com/MatthewHerbst/react-to-print/issues/484)
### Can the `ComponentToPrint` be a functional component?
### Can `react-to-print` be used to change the settings within the print preview dialog?
Yes, but only if you wrap it with [`React.forwardRef`](https://reactjs.org/docs/forwarding-refs.html). `react-to-print` relies on refs to grab the underlying DOM representation of the component, and functional components [cannot take refs by default](https://reactjs.org/docs/refs-and-the-dom.html#accessing-refs).
No. The [`window.print`](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) API does not provide a way to change these settings. Only various CSS hints can be provided, with each browser potentially treating them differently.
### Can the `ComponentToPrint` be a Class component?
Not directly. To print a Class based component you will need to manually forward the `contentRef` as a prop:
```tsx
class ComponentToPrint extends Component {
render() {
return (
<div ref={this.props.innerRef}>
Print content
</div>
)
}
}
function App {
const contentRef = useRef(null);
const handlePrint = useReactToPrint({ contentRef });
return (
<div>
<button onClick={handlePrint}>Print</button>
<ComponentToPrint innerRef={contentRef} />
</div>
);
}
```
### Why does `onAfterPrint` fire even if the user cancels printing

@@ -274,3 +172,3 @@

### Setting state in `onBeforeGetContent`
### Setting state in `onBeforePrint`

@@ -283,3 +181,3 @@ Recall that setting state is asynchronous. As such, you need to pass a `Promise` and wait for the state to update.

// We store the resolve Promise being used in `onBeforeGetContent` here
// We store the resolve Promise being used in `onBeforePrint` here
const promiseResolveRef = useRef(null);

@@ -297,3 +195,3 @@

content: () => printRef.current,
onBeforeGetContent: () => {
onBeforePrint: () => {
return new Promise((resolve) => {

@@ -356,3 +254,3 @@ promiseResolveRef.current = resolve;

### Set custom margin to the page ([29](https://github.com/gregnb/react-to-print/issues/29))
### Set custom margin to the page ([29](https://github.com/MatthewHerbst/react-to-print/issues/29))

@@ -377,3 +275,3 @@ To set custom margin to the page,

### Set landscape printing ([240](https://github.com/gregnb/react-to-print/issues/240))
### Set landscape printing ([240](https://github.com/MatthewHerbst/react-to-print/issues/240))

@@ -388,13 +286,13 @@ In the component that is passed in as the content ref, add the following:

### Printing elements that are not displayed ([159](https://github.com/gregnb/react-to-print/issues/159))
### Printing elements that are not displayed ([159](https://github.com/MatthewHerbst/react-to-print/issues/159))
Instead of using `{ display: 'none'; }`, try using `{ overflow: hidden; height: 0; }`
### Using the `pageStyle` prop
### Using `pageStyle`
The `pageStyle` prop should be a CSS string. For example: `".divider { break-after: always; }"`
`pageStyle` should be a CSS string. For example: `".divider { break-after: always; }"`
### Getting a blank page when printing
Many have found setting the following CSS helpful. See [#26](https://github.com/gregnb/react-to-print/issues/26) for more.
Many have found setting the following CSS helpful. See [#26](https://github.com/MatthewHerbst/react-to-print/issues/26) for more.

@@ -412,9 +310,7 @@ ```css

#### When you've set the `removeAfterPrint` prop to `true`
Another thing to try, especially if you are seeing this issue on mobile browsers, is to set `preserveAfterPrint: true` as it's possible the browser is causing the print iframe to be removed before printing has completed.
If you are getting a blank page while setting `removeAfterPrint` to `true`, try setting it to `false`. This will tell the browser not to remove the `iframe` that we use to print, which it may be doing by mistake, especially on mobile browsers.
### Styles incorrect in print dialog when using grid system
We often ([#327](https://github.com/gregnb/react-to-print/issues/327), [#343](https://github.com/gregnb/react-to-print/issues/343), [#382](https://github.com/gregnb/react-to-print/issues/382)) see issues reported where the developer is using Bootstrap or a similar grid system, and everything works great until the user goes to print and suddenly it seems the styles are off. We've found that often the issue is the grid library uses the smallest sized columns during printing, such as the `xs` size on Bootstrap's grid, a size developers often don't plan for. The simplest solution is to ensure your grid will adapt to this size appropriately, though this may not be acceptable since you may want the large view to print rather than the smaller view. Another solution is to [override the grid column definition](https://stackoverflow.com/questions/22199429/bootstrap-grid-for-printing/28152320). Some newer versions of libraries have specific tools for dealing with printing, for example, [Bootstrap 4's Display property](https://getbootstrap.com/docs/4.3/utilities/display/).
We often ([#327](https://github.com/MatthewHerbst/react-to-print/issues/327), [#343](https://github.com/MatthewHerbst/react-to-print/issues/343), [#382](https://github.com/MatthewHerbst/react-to-print/issues/382)) see issues reported where the developer is using Bootstrap or a similar grid system, and everything works great until the user goes to print and suddenly it seems the styles are off. We've found that often the issue is the grid library uses the smallest sized columns during printing, such as the `xs` size on Bootstrap's grid, a size developers often don't plan for. The simplest solution is to ensure your grid will adapt to this size appropriately, though this may not be acceptable since you may want the large view to print rather than the smaller view. Another solution is to [override the grid column definition](https://stackoverflow.com/questions/22199429/bootstrap-grid-for-printing/28152320). Some newer versions of libraries have specific tools for dealing with printing, for example, [Bootstrap 4's Display property](https://getbootstrap.com/docs/4.3/utilities/display/).

@@ -488,3 +384,3 @@ ### Page Breaks

### Handling Scrolling ([603](https://github.com/gregnb/react-to-print/issues/603))
### Handling Scrolling ([603](https://github.com/MatthewHerbst/react-to-print/issues/603))

@@ -495,4 +391,4 @@ [![Edit react-to-print (Handling Scrolling)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-to-print-handling-scrolling-n4mxyj?fontsize=14&hidenavigation=1&theme=dark)

- [Unable to control the scroll position](https://github.com/gregnb/react-to-print/issues/603#issue-1647664811), so the printed content may not be what you want.
- [Overflow content is truncated](https://github.com/gregnb/react-to-print/issues/603#issuecomment-1649604330), resulting in missing printed content.
- [Unable to control the scroll position](https://github.com/MatthewHerbst/react-to-print/issues/603#issue-1647664811), so the printed content may not be what you want.
- [Overflow content is truncated](https://github.com/MatthewHerbst/react-to-print/issues/603#issuecomment-1649604330), resulting in missing printed content.

@@ -499,0 +395,0 @@ To solve these problems, you need to modify the properties of the scrolling container when printing. You can pass a function to the `print` property, which will be called when printing. In this function, you can use the DOM API to query the scrolling container that needs to be modified, and then modify its properties to **control the scroll position**.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc