@verifiedinc-public/shared-ui-elements 9.8.2 → 9.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
- import { IconButtonProps } from '@mui/material';
2
1
  import { default as React } from 'react';
2
+ import { IconButtonProps } from '@mui/material';
3
3
  /**
4
4
  * A button that exports the content of a target element to a PDF file.
5
+ * Uses html-to-image + jsPDF instead of html2canvas for CSP compliance
6
+ * (html2canvas clones the DOM into an iframe, which violates nonce-based CSP).
5
7
  *
6
8
  * @param {string} targetId - The ID of the target element to export. Without the # symbol.
7
9
  * @param {string} filename - The name of the file to export. Without the .pdf extension.
@@ -1 +1 @@
1
- "use strict";import{PictureAsPdf as c}from"@mui/icons-material";import{IconButton as f,CircularProgress as p}from"@mui/material";import u,{useCallback as g}from"react";import{jsx as o}from"react/jsx-runtime";const h=({targetId:t,filename:s="file",resolution:e,sx:n,...i})=>{const[a,r]=u.useState(!1),l=g(()=>{r(!0),requestAnimationFrame(()=>{setTimeout(()=>{try{import("react-to-pdf").then(async m=>{const d=m.default;await d(()=>typeof t=="string"?document.getElementById(t):t,{filename:`${s}.pdf`,page:{margin:10},...e!==void 0?{resolution:e}:{}})}).finally(()=>{r(!1),console.log("updated pdf")})}catch{r(!1)}},600)})},[s,t,e]);return o("span",{children:o(f,{onClick:l,disabled:a,sx:{m:"0 !important",...n},...i,children:a?o(p,{size:24}):i.children?i.children:o(c,{})})})};export{h as ExportToPdfButton};
1
+ "use strict";import I,{useCallback as C}from"react";import{PictureAsPdf as j}from"@mui/icons-material";import{IconButton as v,CircularProgress as R}from"@mui/material";import{jsx as n}from"react/jsx-runtime";const T=({targetId:t,filename:d="file",resolution:p,sx:P,...r})=>{const[u,a]=I.useState(!1),w=C(()=>{a(!0),requestAnimationFrame(()=>{setTimeout(()=>{(async()=>{try{const e=typeof t=="string"?document.getElementById(t):t?.current;if(!e){a(!1);return}const s=p??2,[{toPng:x},{jsPDF:y}]=await Promise.all([import("html-to-image"),import("jspdf")]),g=e.getBoundingClientRect(),l=20,h=await x(e,{pixelRatio:s,width:g.width+l*2,height:g.height+l*2,style:{margin:`${l}px`}}),i=new Image;i.src=h,await new Promise(F=>{i.onload=()=>F()});const o=10,m=i.width/s,c=i.height/s,B=m>c?"landscape":"portrait",f=new y({orientation:B,unit:"px",format:[m+o*2,c+o*2]});f.addImage(h,"PNG",o,o,m,c),f.save(`${d}.pdf`)}catch(e){console.error("Failed to generate PDF:",e)}finally{a(!1)}})()},600)})},[d,t,p]);return n("span",{children:n(v,{onClick:w,disabled:u,sx:{m:"0 !important",...P},...r,children:u?n(R,{size:24}):r.children?r.children:n(j,{})})})};export{T as ExportToPdfButton};
@@ -7,6 +7,12 @@ interface DateRangeInputProps {
7
7
  onChangeTz?: (startDate: string, endDate: string) => void;
8
8
  /** IANA time zone name (e.g. "America/New_York"). Omit for local time behavior. */
9
9
  timeZone?: string;
10
+ /**
11
+ * CSP nonce applied to the inline <style> tag. Pass this from the server
12
+ * (e.g. Next.js middleware/headers) so the style tag carries a nonce during
13
+ * SSR. Falls back to reading `<meta property="csp-nonce">` on the client.
14
+ */
15
+ nonce?: string;
10
16
  }
11
17
  export declare const DateRangeInput: FC<DateRangeInputProps>;
12
18
  export {};
@@ -1 +1 @@
1
- "use strict";import{useState as p,useRef as T,forwardRef as Y}from"react";import{Box as M,TextField as R}from"@mui/material";import y from"../../../node_modules/react-datepicker/dist/es/index.mjs";import{reactDatepickerCss as C}from"../../../styles/lib/react-datepicker.mjs";import{useOnClickOutside as I}from"../../../hooks/useOnClickOutside.mjs";import{ISO_TZ_FORMAT as l}from"../../../constants/date.mjs";import{useStyle as b}from"./style.mjs";import{jsxs as v,jsx as n}from"react/jsx-runtime";import{fromZonedTime as d}from"../../../node_modules/date-fns-tz/dist/esm/fromZonedTime/index.mjs";import{formatInTimeZone as u}from"../../../node_modules/date-fns-tz/dist/esm/formatInTimeZone/index.mjs";import{toZonedTime as F}from"../../../node_modules/date-fns-tz/dist/esm/toZonedTime/index.mjs";const H=Y(function(e,r){return n(R,{inputRef:r,...e,label:"Range",fullWidth:!0,sx:{flex:1,"& input":{boxShadow:"none!important",border:"none!important"}}})}),O=e=>{const r=b(),f=()=>{const{startDate:o,endDate:t}=e;return!o||!t?[null,null]:[new Date(o),new Date(t)]},[D,w]=p(f()),[c,h]=D,a=T(null),[x,s]=p(!1);return I(a,()=>{s(!1)}),v(M,{ref:a,sx:r.wrapper,children:[n("style",{children:C}),n(y,{open:x,onFocus:()=>{s(!0)},placeholderText:"MM/DD/YYYY - MM/DD/YYYY",showPopperArrow:!1,swapRange:!0,selectsRange:!0,showYearDropdown:!0,showMonthDropdown:!0,scrollableYearDropdown:!1,dateFormat:"MM/dd/yyyy HH:mm:ss",startDate:c??void 0,endDate:h??void 0,minDate:new Date(2023,0,1),maxDate:e.timeZone?F(new Date,e.timeZone):new Date,onChange:([o,t],m)=>{var i;if(w([o,t]),!(!o||!t)&&(((i=m?.target)==null?void 0:i.tagName)!=="INPUT"&&(o.setHours(0,0,0,0),t.setHours(23,59,59,999)),e.onChange(+o,+t),e.timeZone&&e.onChangeTz)){const Z=d(o,e.timeZone),g=d(t,e.timeZone);e.onChangeTz(u(Z,e.timeZone,l),u(g,e.timeZone,l))}},customInput:n(H,{})})]})};export{O as DateRangeInput};
1
+ "use strict";import{useMemo as Y,useState as p,useRef as y,forwardRef as M}from"react";import{Box as R,TextField as v}from"@mui/material";import C from"../../../node_modules/react-datepicker/dist/es/index.mjs";import{reactDatepickerCss as b}from"../../../styles/lib/react-datepicker.mjs";import{useOnClickOutside as I}from"../../../hooks/useOnClickOutside.mjs";import{ISO_TZ_FORMAT as u}from"../../../constants/date.mjs";import{useStyle as S}from"./style.mjs";import{jsxs as F,jsx as n}from"react/jsx-runtime";import{fromZonedTime as l}from"../../../node_modules/date-fns-tz/dist/esm/fromZonedTime/index.mjs";import{formatInTimeZone as d}from"../../../node_modules/date-fns-tz/dist/esm/formatInTimeZone/index.mjs";import{toZonedTime as H}from"../../../node_modules/date-fns-tz/dist/esm/toZonedTime/index.mjs";const O=M(function(e,r){return n(v,{inputRef:r,...e,label:"Range",fullWidth:!0,sx:{flex:1,"& input":{boxShadow:"none!important",border:"none!important"}}})}),k=e=>{const r=S(),c=Y(()=>{var o;if(e.nonce)return e.nonce;if(!(typeof document>"u"))return((o=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:o.getAttribute("content"))??void 0},[e.nonce]),f=()=>{const{startDate:o,endDate:t}=e;return!o||!t?[null,null]:[new Date(o),new Date(t)]},[D,w]=p(f()),[h,g]=D,a=y(null),[x,s]=p(!1);return I(a,()=>{s(!1)}),F(R,{ref:a,sx:r.wrapper,children:[n("style",{nonce:c,children:b}),n(C,{open:x,onFocus:()=>{s(!0)},placeholderText:"MM/DD/YYYY - MM/DD/YYYY",showPopperArrow:!1,swapRange:!0,selectsRange:!0,showYearDropdown:!0,showMonthDropdown:!0,scrollableYearDropdown:!1,dateFormat:"MM/dd/yyyy HH:mm:ss",startDate:h??void 0,endDate:g??void 0,minDate:new Date(2023,0,1),maxDate:e.timeZone?H(new Date,e.timeZone):new Date,onChange:([o,t],m)=>{var i;if(w([o,t]),!(!o||!t)&&(((i=m?.target)==null?void 0:i.tagName)!=="INPUT"&&(o.setHours(0,0,0,0),t.setHours(23,59,59,999)),e.onChange(+o,+t),e.timeZone&&e.onChangeTz)){const Z=l(o,e.timeZone),T=l(t,e.timeZone);e.onChangeTz(d(Z,e.timeZone,u),d(T,e.timeZone,u))}},customInput:n(O,{})})]})};export{k as DateRangeInput};
@@ -1 +1 @@
1
- "use strict";import{forwardRef as z,useRef as G,useState as p,useImperativeHandle as N,useEffect as v}from"react";import{Stack as y,Box as F,Button as W}from"@mui/material";import{AutoAwesome as $}from"@mui/icons-material";import*as u from"html-to-image";import{wrapPromise as j}from"../../utils/wrapPromise/index.mjs";import{useGoogleFont as A}from"../../hooks/useGoogleFont.mjs";import{jsxs as L,jsx as i}from"react/jsx-runtime";import{PoweredByVerified as H}from"../verified/powered-by-verified/index.mjs";function V({magicLink:g,magicText:c,buttonProps:l,renderAsImage:n,enablePoweredByVerified:b,poweredByVerifiedProps:d,fontFamily:s,enableGoogleFontLoad:h},R){const o=G(null),[C,S]=p(null),[P,E]=p(null),[m,x]=p(0),[k,T]=p(0),r=A(s,h),B=async e=>{if(!o.current)return;const a={png:u.toPng,svg:u.toSvg};let t=null;try{r.cssContent&&(t=document.createElement("style"),t.id="temp-font-style-for-download",t.textContent=r.cssContent,document.head.appendChild(t));const[f,I]=await j(a[e](o.current,{pixelRatio:4}));if(t&&(document.head.removeChild(t),t=null),I){console.error("Failed to generate magic button:",I);return}if(!f)return;const w=document.createElement("a");w.href=f,w.download=`magic-button-${c.replace(/\s+/g,"-")}.${e}`,w.click()}catch(f){t&&document.head.removeChild(t),console.error("Failed to generate magic button:",f)}};return N(R,()=>({download:B}),[B]),v(()=>{if(!n){x(0);return}if(!o.current||m>10)return;x(a=>a+1);const e=setInterval(()=>{x(a=>a+1)},m+1*500);return()=>clearInterval(e)},[m,n,r.isLoaded]),v(()=>{let e=null;return r.cssContent&&(e=document.createElement("style"),e.id="temp-font-style-for-image",e.textContent=r.cssContent,document.head.appendChild(e)),()=>{e&&document.head.removeChild(e)}},[r.cssContent]),v(()=>{!n||s&&h&&r.isLoading||(async()=>{if(o.current&&!(h&&!r.isLoaded))try{const e=await u.toPng(o.current,{pixelRatio:.5});if(e===P){k===0&&T(t=>t+1);return}if(E(e),!o.current)return;const a=await u.toPng(o.current,{pixelRatio:4});S(a)}catch(e){console.error("Failed to generate PNG:",e)}})()},[k,m,g,c,l,b,d,n,s,r.isLoaded,P]),L(y,{children:[i(F,{className:"button-preview-container",sx:{...n&&{position:"fixed",top:-9999,left:-9999,maxWidth:9999,overflow:"hidden",zIndex:-1}},children:L(y,{ref:o,className:"canvas-copiable",spacing:1,sx:{display:"inline-flex",minWidth:"fit-content",justifyContent:"center",alignItems:"center",alignSelf:"center",...n&&{pt:"3px",pb:"6px",px:"4px"}},children:[i(W,{href:g,target:"_blank",variant:"contained",size:"large",color:"primary",startIcon:i($,{}),...l,sx:{fontFamily:s?`"${s}" !important`:void 0,textTransform:"none",fontSize:16,p:1.5,m:1,"&, & > span":{wordBreak:"break-word",lineHeight:n?0:1.75},"& > span":{whiteSpace:n?"nowrap":void 0},...l?.sx},children:i("span",{children:c})}),b&&i(H,{...d,containerProps:{pt:.5,maxWidth:143,...d?.containerProps}})]})}),C&&n&&i(y,{component:"a",href:g,target:"_blank",rel:"noopener noreferrer",flex:1,sx:{overflow:"visible"},children:i(F,{component:"img",src:C,alt:c,draggable:!1,sx:{width:"100%",height:"auto"}})})]})}const _=z(V);export{_ as TTSMagicButton};
1
+ "use strict";import{forwardRef as z,useRef as G,useState as f,useImperativeHandle as N,useEffect as b}from"react";import{Stack as y,Box as F,Button as W}from"@mui/material";import{AutoAwesome as $}from"@mui/icons-material";import*as g from"html-to-image";import{wrapPromise as q}from"../../utils/wrapPromise/index.mjs";import{useGoogleFont as H}from"../../hooks/useGoogleFont.mjs";import{jsxs as L,jsx as i}from"react/jsx-runtime";import{PoweredByVerified as V}from"../verified/powered-by-verified/index.mjs";function _({magicLink:h,magicText:l,buttonProps:d,renderAsImage:r,enablePoweredByVerified:C,poweredByVerifiedProps:m,fontFamily:s,enableGoogleFontLoad:x},R){const a=G(null),[P,E]=f(null),[S,T]=f(null),[p,v]=f(0),[k,j]=f(0),o=H(s,x),A=async t=>{var e;if(!a.current)return;const c={png:g.toPng,svg:g.toSvg};let n=null;try{if(o.cssContent){n=document.createElement("style"),n.id="temp-font-style-for-download";const B=(e=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:e.getAttribute("content");B&&n.setAttribute("nonce",B),n.textContent=o.cssContent,document.head.appendChild(n)}const[u,I]=await q(c[t](a.current,{pixelRatio:4}));if(n&&(document.head.removeChild(n),n=null),I){console.error("Failed to generate magic button:",I);return}if(!u)return;const w=document.createElement("a");w.href=u,w.download=`magic-button-${l.replace(/\s+/g,"-")}.${t}`,w.click()}catch(u){n&&document.head.removeChild(n),console.error("Failed to generate magic button:",u)}};return N(R,()=>({download:A}),[A]),b(()=>{if(!r){v(0);return}if(!a.current||p>10)return;v(e=>e+1);const t=setInterval(()=>{v(e=>e+1)},p+1*500);return()=>clearInterval(t)},[p,r,o.isLoaded]),b(()=>{var t;let e=null;if(o.cssContent){e=document.createElement("style"),e.id="temp-font-style-for-image";const c=(t=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:t.getAttribute("content");c&&e.setAttribute("nonce",c),e.textContent=o.cssContent,document.head.appendChild(e)}return()=>{e&&document.head.removeChild(e)}},[o.cssContent]),b(()=>{!r||s&&x&&o.isLoading||(async()=>{if(a.current&&!(x&&!o.isLoaded))try{const t=await g.toPng(a.current,{pixelRatio:.5});if(t===S){k===0&&j(c=>c+1);return}if(T(t),!a.current)return;const e=await g.toPng(a.current,{pixelRatio:4});E(e)}catch(t){console.error("Failed to generate PNG:",t)}})()},[k,p,h,l,d,C,m,r,s,o.isLoaded,S]),L(y,{children:[i(F,{className:"button-preview-container",sx:{...r&&{position:"fixed",top:-9999,left:-9999,maxWidth:9999,overflow:"hidden",zIndex:-1}},children:L(y,{ref:a,className:"canvas-copiable",spacing:1,sx:{display:"inline-flex",minWidth:"fit-content",justifyContent:"center",alignItems:"center",alignSelf:"center",...r&&{pt:"3px",pb:"6px",px:"4px"}},children:[i(W,{href:h,target:"_blank",variant:"contained",size:"large",color:"primary",startIcon:i($,{}),...d,sx:{fontFamily:s?`"${s}" !important`:void 0,textTransform:"none",fontSize:16,p:1.5,m:1,"&, & > span":{wordBreak:"break-word",lineHeight:r?0:1.75},"& > span":{whiteSpace:r?"nowrap":void 0},...d?.sx},children:i("span",{children:l})}),C&&i(V,{...m,containerProps:{pt:.5,maxWidth:143,...m?.containerProps}})]})}),P&&r&&i(y,{component:"a",href:h,target:"_blank",rel:"noopener noreferrer",flex:1,sx:{overflow:"visible"},children:i(F,{component:"img",src:P,alt:l,draggable:!1,sx:{width:"100%",height:"auto"}})})]})}const D=z(_);export{D as TTSMagicButton};
@@ -1 +1 @@
1
- "use strict";import{useState as i,useEffect as g}from"react";import{makeGoogleFontUrl as f}from"../utils/makeGoogleFont.mjs";function h(r,u){const[d,o]=i("idle"),[m,a]=i(null);return g(()=>{if(!r||!u){o("idle"),a(null);return}const s=`google-font-${r.replace(/\s+/g,"-").toLowerCase()}`,l=document.getElementById(s);if(l){const e=l.getAttribute("data-status"),t=l.getAttribute("data-css-content");e==="loaded"&&t?(o("loaded"),a(t)):e==="error"?(o("error"),a(null)):o("loading");return}return o("loading"),a(null),(async()=>{try{const e=f(r),t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch font CSS: ${t.statusText}`);const c=await t.text(),n=document.createElement("style");n.id=s,n.textContent=c,n.setAttribute("data-status","loaded"),n.setAttribute("data-css-content",c),document.head.appendChild(n),o("loaded"),a(c)}catch(e){console.error(`Failed to load Google Font ${r}:`,e);const t=document.createElement("style");t.id=s,t.setAttribute("data-status","error"),document.head.appendChild(t),o("error"),a(null)}})(),()=>{const e=document.getElementById(s);e&&document.head.removeChild(e)}},[r,u]),{status:d,isLoading:d==="loading",isLoaded:d==="loaded",hasError:d==="error",cssContent:m}}export{h as useGoogleFont};
1
+ "use strict";import{useState as p,useEffect as h}from"react";import{makeGoogleFontUrl as y}from"../utils/makeGoogleFont.mjs";function b(d,m){const[l,o]=p("idle"),[f,n]=p(null);return h(()=>{if(!d||!m){o("idle"),n(null);return}const u=`google-font-${d.replace(/\s+/g,"-").toLowerCase()}`,c=document.getElementById(u);if(c){const t=c.getAttribute("data-status"),s=c.getAttribute("data-css-content");t==="loaded"&&s?(o("loaded"),n(s)):t==="error"?(o("error"),n(null)):o("loading");return}return o("loading"),n(null),(async()=>{var t,s;try{const i=y(d),e=await fetch(i);if(!e.ok)throw new Error(`Failed to fetch font CSS: ${e.statusText}`);const r=await e.text(),a=document.createElement("style");a.id=u;const g=(t=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:t.getAttribute("content");g&&a.setAttribute("nonce",g),a.textContent=r,a.setAttribute("data-status","loaded"),a.setAttribute("data-css-content",r),document.head.appendChild(a),o("loaded"),n(r)}catch(i){console.error(`Failed to load Google Font ${d}:`,i);const e=document.createElement("style");e.id=u;const r=(s=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:s.getAttribute("content");r&&e.setAttribute("nonce",r),e.setAttribute("data-status","error"),document.head.appendChild(e),o("error"),n(null)}})(),()=>{const t=document.getElementById(u);t&&document.head.removeChild(t)}},[d,m]),{status:l,isLoading:l==="loading",isLoaded:l==="loaded",hasError:l==="error",cssContent:f}}export{b as useGoogleFont};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verifiedinc-public/shared-ui-elements",
3
- "version": "9.8.2",
3
+ "version": "9.9.0",
4
4
  "description": "A set of UI components, utilities that is shareable with the core apps.",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -137,6 +137,7 @@
137
137
  "framer-motion": ">=11.11.1",
138
138
  "html-to-image": ">=1.11.13 <2",
139
139
  "immer": ">=10",
140
+ "jspdf": ">=4.2.1 <5",
140
141
  "libphonenumber-js": ">=1.11.11",
141
142
  "lodash": ">=4.17.21",
142
143
  "notistack": ">=3.0.1",
@@ -148,7 +149,6 @@
148
149
  "react-dom": ">=18 <19",
149
150
  "react-hook-form": ">=7.52.1 <=7.53.2",
150
151
  "react-imask": ">=7.6.1",
151
- "react-to-pdf": ">=3.0.0",
152
152
  "recharts": ">=2.15.0 <3",
153
153
  "tinycolor2": ">=1.6.0 <2",
154
154
  "uuid": ">=9.0.1",