@contentful/f36-copybutton 5.0.0 → 5.1.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.
package/README.mdx CHANGED
@@ -45,6 +45,14 @@ To read more about all possible values of `tooltipProps` object, refer to [Toolt
45
45
 
46
46
  ```
47
47
 
48
+ ### Using with promises
49
+
50
+ Sometimes you want to await a Promise before know the value to copy to the clipboard. You can do this in the code where the copy button is implemented.
51
+
52
+ ```jsx file=examples/CopyButtonWithPromiseExample.tsx
53
+
54
+ ```
55
+
48
56
  ## Accessibility
49
57
 
50
58
  You can pass a custom `aria-label` through the `label` prop.
package/dist/esm/index.js CHANGED
@@ -1,11 +1,12 @@
1
- import { cx, css } from 'emotion';
2
- import n, { useState, useRef, useCallback } from 'react';
3
- import j from 'react-copy-to-clipboard';
4
- import { CopyIcon } from '@contentful/f36-icons';
1
+ import d, { useState, useCallback } from 'react';
2
+ import V from '@contentful/f36-tokens';
3
+ import { CopySimpleIcon } from '@contentful/f36-icons';
5
4
  import { Tooltip } from '@contentful/f36-tooltip';
6
- import i from '@contentful/f36-tokens';
5
+ import { Button } from '@contentful/f36-button';
6
+ import { cx, css } from 'emotion';
7
7
 
8
- var N=Object.defineProperty,$=Object.defineProperties;var I=Object.getOwnPropertyDescriptors;var s=Object.getOwnPropertySymbols;var f=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;var b=(o,t,e)=>t in o?N(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,u=(o,t)=>{for(var e in t||(t={}))f.call(t,e)&&b(o,e,t[e]);if(s)for(var e of s(t))C.call(t,e)&&b(o,e,t[e]);return o},g=(o,t)=>$(o,I(t));var x=(o,t)=>{var e={};for(var r in o)f.call(o,r)&&t.indexOf(r)<0&&(e[r]=o[r]);if(o!=null&&s)for(var r of s(o))t.indexOf(r)<0&&C.call(o,r)&&(e[r]=o[r]);return e};var h=({size:o})=>{let t=o==="small"?"32px":"40px";return {wrapper:css({display:"inline-block",height:t,position:"relative",width:t}),copyButton:css({alignItems:"center",background:i.colorWhite,border:`1px solid ${i.gray300}`,display:"inline-flex",height:"100%",justifyContent:"center",outline:"none",padding:0,transition:`background ${i.transitionDurationShort} ${i.transitionEasingDefault}`,width:"100%","&:hover":{backgroundColor:i.gray100,cursor:"pointer"},"&:active":{backgroundColor:i.gray200,cursor:"pointer"},"&:focus":{boxShadow:i.glowMuted},"&:focus:not(:focus-visible)":{boxShadow:"unset"},"&:focus-visible":{boxShadow:i.glowMuted}}),copyButtonDisabled:css({cursor:"not-allowed",backgroundColor:i.gray100,"&:hover":{cursor:"not-allowed",backgroundColor:i.gray100},"&:focus":{borderColor:i.gray300,boxShadow:"none"},"&:active, &:active:hover":{borderColor:i.gray300,boxShadow:"none"}})}};function w(o,t){let y=o,{onCopy:e,value:r,className:B,testId:T="cf-ui-copy-button",tooltipText:P="Copy to clipboard",tooltipCopiedText:S="Copied!",tooltipProps:k,isDisabled:p=!1,size:c="medium"}=y,D=x(y,["onCopy","value","className","testId","tooltipText","tooltipCopiedText","tooltipProps","isDisabled","size"]),l=h({size:c}),[E,m]=useState(!1),a=useRef(null),z=useCallback(M=>{e&&e(M),m(!0),setTimeout(()=>{m(!1),a.current&&a.current.blur();},1e3);},[e]);return n.createElement("div",u({ref:t,"data-test-id":T,className:cx(l.wrapper,B)},D),n.createElement(j,{text:r,onCopy:z},n.createElement(Tooltip,g(u({content:E?S:P},k),{isDisabled:p}),n.createElement("button",{type:"button",ref:a,className:cx(l.copyButton,{[l.copyButtonDisabled]:p}),"aria-label":`Copy ${r} to clipboard`,disabled:p,"aria-live":"assertive"},n.createElement(CopyIcon,{variant:"muted",size:c==="small"?"tiny":"small"})))))}w.displayName="CopyButton";var q=n.forwardRef(w);
8
+ var L=Object.defineProperty,F=Object.defineProperties;var N=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,E=Object.prototype.propertyIsEnumerable;var x=(t,o,e)=>o in t?L(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,f=(t,o)=>{for(var e in o||(o={}))v.call(o,e)&&x(t,e,o[e]);if(m)for(var e of m(o))E.call(o,e)&&x(t,e,o[e]);return t},C=(t,o)=>F(t,N(o));var w=(t,o)=>{var e={};for(var n in t)v.call(t,n)&&o.indexOf(n)<0&&(e[n]=t[n]);if(t!=null&&m)for(var n of m(t))o.indexOf(n)<0&&E.call(t,n)&&(e[n]=t[n]);return e};var T=(t,o,e)=>new Promise((n,s)=>{var i=r=>{try{a(e.next(r));}catch(l){s(l);}},c=r=>{try{a(e.throw(r));}catch(l){s(l);}},a=r=>r.done?n(r.value):Promise.resolve(r.value).then(i,c);a((e=e.apply(t,o)).next());});var H=({size:t})=>{let o=t==="small"?"32px":"40px";return {button:css({height:o,minWidth:"auto",width:o,"span:first-child":{marginRight:0}})}};function k(G,S){var P=G,{className:t,isDisabled:o=!1,isLoading:e=!1,label:n,onBlur:s,onCopy:i,size:c="medium",testId:a="cf-ui-copy-button",tooltipCopiedText:r="Value copied to clipboard",tooltipProps:l,tooltipText:B="Copy to clipboard",value:u}=P,M=w(P,["className","isDisabled","isLoading","label","onBlur","onCopy","size","testId","tooltipCopiedText","tooltipProps","tooltipText","value"]);let z=H({size:c}),[y,b]=useState(!1),I=useCallback(()=>T(this,null,function*(){try{yield window.navigator.clipboard.writeText(u);}catch(g){let p=document.createElement("input");p.style.display="none",document.body.appendChild(p),p.value=u,p.focus(),p.select();let h=document.execCommand("copy");if(h==="unsuccessful")throw new Error("Unable to copy value",{cause:h});p.remove();return}i==null||i(u),b(!0);}),[i,u]),D=g=>{y&&b(!1),s==null||s(g);};return d.createElement(Tooltip,C(f({content:y?r:B},l),{isDisabled:o}),d.createElement(Button,C(f({"aria-label":y?r:n!=null?n:B,"aria-live":"assertive",className:cx(z.button,t),isDisabled:e||o,isLoading:e,onBlur:D,testId:a,startIcon:d.createElement(CopySimpleIcon,{color:V.gray600,size:c==="small"?"tiny":"small"}),variant:"secondary"},M),{onClick:I,ref:S})))}k.displayName="CopyButton";var A=d.forwardRef(k);
9
9
 
10
- export { q as CopyButton };
10
+ export { A as CopyButton };
11
+ //# sourceMappingURL=out.js.map
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/CopyButton.tsx","../../src/CopyButton.styles.ts"],"names":["cx","React","useState","useCallback","useRef","CopyToClipboard","CopyIcon","Tooltip","css","tokens","getStyles","size","buttonSize","_CopyButton","props","ref","_a","onCopy","value","className","testId","tooltipText","tooltipCopiedText","tooltipProps","isDisabled","otherProps","__objRest","styles","copied","setCopied","button","handleOnCopy","e","__spreadValues","__spreadProps","CopyButton"],"mappings":"+kBAAA,OAAS,MAAAA,MAAU,UACnB,OAAOC,GAAS,YAAAC,EAAU,eAAAC,EAAa,UAAAC,MAAc,QACrD,OAAOC,MAAqB,0BAC5B,OAAS,YAAAC,MAAgB,wBAEzB,OAAS,WAAAC,MAAkC,0BCL3C,OAAS,OAAAC,MAAW,UACpB,OAAOC,MAAY,yBAEZ,IAAMC,EAAY,CAAC,CAAE,KAAAC,CAAK,IAAM,CACrC,IAAMC,EAAaD,IAAS,QAAU,OAAS,OAE/C,MAAO,CACL,QAASH,EAAI,CACX,QAAS,eACT,OAAQI,EACR,SAAU,WACV,MAAOA,CACT,CAAC,EACD,WAAYJ,EAAI,CACd,WAAY,SACZ,WAAYC,EAAO,WACnB,OAAQ,aAAaA,EAAO,UAC5B,QAAS,cACT,OAAQ,OACR,eAAgB,SAChB,QAAS,OACT,QAAS,EACT,WAAY,cAAcA,EAAO,2BAA2BA,EAAO,0BACnE,MAAO,OACP,UAAW,CACT,gBAAiBA,EAAO,QACxB,OAAQ,SACV,EACA,WAAY,CACV,gBAAiBA,EAAO,QACxB,OAAQ,SACV,EACA,UAAW,CACT,UAAWA,EAAO,SACpB,EACA,8BAA+B,CAC7B,UAAW,OACb,EACA,kBAAmB,CACjB,UAAWA,EAAO,SACpB,CACF,CAAC,EACD,mBAAoBD,EAAI,CACtB,OAAQ,cACR,gBAAiBC,EAAO,QAExB,UAAW,CACT,OAAQ,cACR,gBAAiBA,EAAO,OAC1B,EAEA,UAAW,CACT,YAAaA,EAAO,QACpB,UAAW,MACb,EAEA,2BAA4B,CAC1B,YAAaA,EAAO,QACpB,UAAW,MACb,CACF,CAAC,CACH,CACF,EDdA,SAASI,EACPC,EACAC,EACA,CACA,IAWIC,EAAAF,EAVF,QAAAG,EACA,MAAAC,EACA,UAAAC,EACA,OAAAC,EAAS,oBACT,YAAAC,EAAc,oBACd,kBAAAC,EAAoB,UACpB,aAAAC,EACA,WAAAC,EAAa,GACb,KAAAb,EAAO,QA7DX,EA+DMK,EADCS,EAAAC,EACDV,EADC,CATH,SACA,QACA,YACA,SACA,cACA,oBACA,eACA,aACA,SAGIW,EAASjB,EAAU,CAAE,KAAAC,CAAK,CAAC,EAE3B,CAACiB,EAAQC,CAAS,EAAI3B,EAAS,EAAK,EACpC4B,EAAS1B,EAAiC,IAAI,EAC9C2B,EAAe5B,EAClB6B,GAAc,CACTf,GACFA,EAAOe,CAAC,EAGVH,EAAU,EAAI,EAEd,WAAW,IAAM,CACfA,EAAU,EAAK,EACXC,EAAO,SACTA,EAAO,QAAQ,KAAK,CAExB,EAAG,GAAI,CACT,EACA,CAACb,CAAM,CACT,EAEA,OACEhB,EAAA,cAAC,MAAAgC,EAAA,CACC,IAAKlB,EACL,eAAcK,EACd,UAAWpB,EAAG2B,EAAO,QAASR,CAAS,GACnCM,GAEJxB,EAAA,cAACI,EAAA,CAAgB,KAAMa,EAAO,OAAQa,GACpC9B,EAAA,cAACM,EAAA2B,EAAAD,EAAA,CACC,QAASL,EAASN,EAAoBD,GAClCE,GAFL,CAGC,WAAYC,IAEZvB,EAAA,cAAC,UACC,KAAK,SACL,IAAK6B,EACL,UAAW9B,EAAG2B,EAAO,WAAY,CAC/B,CAACA,EAAO,oBAAqBH,CAC/B,CAAC,EACD,aAAY,QAAQN,iBACpB,SAAUM,EACV,YAAU,aAEVvB,EAAA,cAACK,EAAA,CACC,QAAQ,QACR,KAAMK,IAAS,QAAU,OAAS,QACpC,CACF,CACF,CACF,CACF,CAEJ,CAEAE,EAAY,YAAc,aAEnB,IAAMsB,EAAalC,EAAM,WAAWY,CAAW","sourcesContent":["import { cx } from 'emotion';\nimport React, { useState, useCallback, useRef } from 'react';\nimport CopyToClipboard from 'react-copy-to-clipboard';\nimport { CopyIcon } from '@contentful/f36-icons';\nimport type { CommonProps, ExpandProps } from '@contentful/f36-core';\nimport { Tooltip, type TooltipProps } from '@contentful/f36-tooltip';\nimport { getStyles } from './CopyButton.styles';\n\nexport interface CopyButtonProps extends CommonProps {\n /**\n * Function that gets called when the button is clicked\n */\n onCopy?: (string) => void;\n /**\n * Text to be shown when the button is clicked\n * @default Copied!\n */\n tooltipCopiedText?: string;\n /**\n * Text to be shown when button is hovered or focused\n * @default Copy to clipboard\n */\n tooltipText?: string;\n /**\n * Props that are passed to the tooltip component\n */\n tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;\n /**\n * Value that will be copied to clipboard when the button is clicked\n */\n value: string;\n /**\n * Label to be used on aria-label for the button\n * @default Copy {value} to clipboard\n */\n label?: string;\n /**\n * Allows to disable the copy button, when true the tooltip would not be shown\n * @default false\n */\n isDisabled?: boolean;\n /**\n * Allows setting size of the copy button to small\n * @default medium\n */\n size?: 'small' | 'medium';\n}\n\nfunction _CopyButton(\n props: ExpandProps<CopyButtonProps>,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {\n onCopy,\n value,\n className,\n testId = 'cf-ui-copy-button',\n tooltipText = 'Copy to clipboard',\n tooltipCopiedText = 'Copied!',\n tooltipProps,\n isDisabled = false,\n size = 'medium',\n ...otherProps\n } = props;\n const styles = getStyles({ size });\n\n const [copied, setCopied] = useState(false);\n const button = useRef<HTMLButtonElement | null>(null);\n const handleOnCopy = useCallback(\n (e: string) => {\n if (onCopy) {\n onCopy(e);\n }\n\n setCopied(true);\n\n setTimeout(() => {\n setCopied(false);\n if (button.current) {\n button.current.blur();\n }\n }, 1000);\n },\n [onCopy],\n );\n\n return (\n <div\n ref={ref}\n data-test-id={testId}\n className={cx(styles.wrapper, className)}\n {...otherProps}\n >\n <CopyToClipboard text={value} onCopy={handleOnCopy}>\n <Tooltip\n content={copied ? tooltipCopiedText : tooltipText}\n {...tooltipProps}\n isDisabled={isDisabled}\n >\n <button\n type=\"button\"\n ref={button}\n className={cx(styles.copyButton, {\n [styles.copyButtonDisabled]: isDisabled,\n })}\n aria-label={`Copy ${value} to clipboard`}\n disabled={isDisabled}\n aria-live=\"assertive\"\n >\n <CopyIcon\n variant=\"muted\"\n size={size === 'small' ? 'tiny' : 'small'}\n />\n </button>\n </Tooltip>\n </CopyToClipboard>\n </div>\n );\n}\n\n_CopyButton.displayName = 'CopyButton';\n\nexport const CopyButton = React.forwardRef(_CopyButton);\n","import { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nexport const getStyles = ({ size }) => {\n const buttonSize = size === 'small' ? '32px' : '40px';\n\n return {\n wrapper: css({\n display: 'inline-block',\n height: buttonSize,\n position: 'relative',\n width: buttonSize,\n }),\n copyButton: css({\n alignItems: 'center',\n background: tokens.colorWhite,\n border: `1px solid ${tokens.gray300}`,\n display: 'inline-flex',\n height: '100%',\n justifyContent: 'center',\n outline: 'none',\n padding: 0,\n transition: `background ${tokens.transitionDurationShort} ${tokens.transitionEasingDefault}`,\n width: '100%',\n '&:hover': {\n backgroundColor: tokens.gray100,\n cursor: 'pointer',\n },\n '&:active': {\n backgroundColor: tokens.gray200,\n cursor: 'pointer',\n },\n '&:focus': {\n boxShadow: tokens.glowMuted,\n },\n '&:focus:not(:focus-visible)': {\n boxShadow: 'unset',\n },\n '&:focus-visible': {\n boxShadow: tokens.glowMuted,\n },\n }),\n copyButtonDisabled: css({\n cursor: 'not-allowed',\n backgroundColor: tokens.gray100,\n\n '&:hover': {\n cursor: 'not-allowed',\n backgroundColor: tokens.gray100,\n },\n\n '&:focus': {\n borderColor: tokens.gray300,\n boxShadow: 'none',\n },\n\n '&:active, &:active:hover': {\n borderColor: tokens.gray300,\n boxShadow: 'none',\n },\n }),\n };\n};\n"]}
1
+ {"version":3,"sources":["../../src/CopyButton.tsx","../../src/CopyButton.styles.ts"],"names":["React","useCallback","useState","tokens","CopySimpleIcon","Tooltip","Button","css","getCopyButtonStyles","size","buttonSize","cx","_CopyButton","_a","ref","_b","className","isDisabled","isLoading","label","onBlur","onCopy","testId","tooltipCopiedText","tooltipProps","tooltipText","value","otherProps","__objRest","styles","copied","setCopied","handleClick","__async","error","input","result","handleBlur","event","__spreadProps","__spreadValues","CopyButton"],"mappings":"4xBAAA,OAAOA,GACL,eAAAC,EACA,YAAAC,MAGK,QACP,OAAOC,MAAY,yBACnB,OAAS,kBAAAC,MAAsB,wBAE/B,OAAS,WAAAC,MAAkC,0BAC3C,OAAS,UAAAC,MAAgC,yBCVzC,OAAS,OAAAC,MAAW,UAGb,IAAMC,EAAsB,CAAC,CAClC,KAAAC,CACF,IAAqC,CACnC,IAAMC,EAAaD,IAAS,QAAU,OAAS,OAE/C,MAAO,CACL,OAAQF,EAAI,CACV,OAAQG,EACR,SAAU,OACV,MAAOA,EAEP,mBAAoB,CAAE,YAAa,CAAE,CACvC,CAAC,CACH,CACF,EDLA,OAAS,MAAAC,MAAU,UA6CnB,SAASC,EACPC,EAeAC,EACA,CAhBA,IAAAC,EAAAF,EACE,WAAAG,EACA,WAAAC,EAAa,GACb,UAAAC,EAAY,GACZ,MAAAC,EACA,OAAAC,EACA,OAAAC,EACA,KAAAZ,EAAO,SACP,OAAAa,EAAS,oBACT,kBAAAC,EAAoB,4BACpB,aAAAC,EACA,YAAAC,EAAc,oBACd,MAAAC,CAtEJ,EA0DEX,EAaKY,EAAAC,EAbLb,EAaK,CAZH,YACA,aACA,YACA,QACA,SACA,SACA,OACA,SACA,oBACA,eACA,cACA,UAKF,IAAMc,EAASrB,EAAoB,CAAE,KAAAC,CAAK,CAAC,EACrC,CAACqB,EAAQC,CAAS,EAAI7B,EAAS,EAAK,EAEpC8B,EAAc/B,EAElB,IAAYgC,EAAA,sBACZ,GAAI,CACF,MAAM,OAAO,UAAU,UAAU,UAAUP,CAAK,CAClD,OAASQ,EAAO,CAGd,IAAMC,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,MAAM,QAAU,OACtB,SAAS,KAAK,YAAYA,CAAK,EAC/BA,EAAM,MAAQT,EACdS,EAAM,MAAM,EACZA,EAAM,OAAO,EACb,IAAMC,EAAS,SAAS,YAAY,MAAM,EAG1C,GAAIA,IAAW,eACb,MAAM,IAAI,MAAM,uBAAwB,CAAE,MAAOA,CAAO,CAAC,EAE3DD,EAAM,OAAO,EAEb,MACF,CAEAd,GAAA,MAAAA,EAASK,GACTK,EAAU,EAAI,CAChB,GAAG,CAACV,EAAQK,CAAK,CAAC,EAEZW,EAAoDC,GAAU,CAC9DR,GACFC,EAAU,EAAK,EAGjBX,GAAA,MAAAA,EAASkB,EACX,EAEA,OACEtC,EAAA,cAACK,EAAAkC,EAAAC,EAAA,CACC,QAASV,EAASP,EAAoBE,GAClCD,GAFL,CAGC,WAAYP,IAEZjB,EAAA,cAACM,EAAAiC,EAAAC,EAAA,CACC,aAAYV,EAASP,EAAoBJ,GAAA,KAAAA,EAASM,EAClD,YAAU,YACV,UAAWd,EAAGkB,EAAO,OAAQb,CAAS,EACtC,WAAYE,GAAaD,EACzB,UAAWC,EACX,OAAQmB,EACR,OAAQf,EACR,UACEtB,EAAA,cAACI,EAAA,CACC,MAAOD,EAAO,QACd,KAAMM,IAAS,QAAU,OAAS,QACpC,EAEF,QAAQ,aACJkB,GAfL,CAgBC,QAASK,EACT,IAAKlB,GACP,CACF,CAEJ,CAEAF,EAAY,YAAc,aAEnB,IAAM6B,EAAazC,EAAM,WAAWY,CAAW","sourcesContent":["import React, {\n useCallback,\n useState,\n type MouseEventHandler,\n type FocusEventHandler,\n} from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { CopySimpleIcon } from '@contentful/f36-icons';\nimport type { ExpandProps } from '@contentful/f36-core';\nimport { Tooltip, type TooltipProps } from '@contentful/f36-tooltip';\nimport { Button, type ButtonProps } from '@contentful/f36-button';\nimport { getCopyButtonStyles } from './CopyButton.styles';\nimport { cx } from 'emotion';\n\nexport type CopyButtonProps = Omit<\n ButtonProps,\n 'endIcon' | 'onCopy' | 'onClick' | 'isDisabled' | 'size' | 'value'\n> & {\n /**\n * Function that gets called when the button is clicked\n */\n onCopy?: (string) => void;\n /**\n * Text to be shown when the button is clicked\n * @default Copied!\n */\n tooltipCopiedText?: string;\n /**\n * Text to be shown when button is hovered or focused\n * @default Copy to clipboard\n */\n tooltipText?: string;\n /**\n * Props that are passed to the tooltip component\n */\n tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;\n /**\n * Label to be used on aria-label for the button\n * @default Copy to clipboard\n */\n label?: string;\n /**\n * Allows to disable the copy button, when true the tooltip would not be shown\n * @default false\n */\n isDisabled?: boolean;\n /**\n * Allows setting size of the copy button to small\n * @default medium\n */\n size?: 'small' | 'medium';\n /**\n * Value that will be copied to clipboard when the button is clicked\n */\n value: string;\n};\n\nfunction _CopyButton(\n {\n className,\n isDisabled = false,\n isLoading = false,\n label,\n onBlur,\n onCopy,\n size = 'medium',\n testId = 'cf-ui-copy-button',\n tooltipCopiedText = 'Value copied to clipboard',\n tooltipProps,\n tooltipText = 'Copy to clipboard',\n value,\n ...otherProps\n }: ExpandProps<CopyButtonProps>,\n ref: React.Ref<HTMLButtonElement>,\n) {\n const styles = getCopyButtonStyles({ size });\n const [copied, setCopied] = useState(false);\n\n const handleClick = useCallback<\n MouseEventHandler<HTMLButtonElement>\n >(async () => {\n try {\n await window.navigator.clipboard.writeText(value);\n } catch (error) {\n // Chrome requires specific permissions on iframes using the async clipboard\n // API. We can't control that so we fall back to this\n const input = document.createElement('input');\n input.style.display = 'none';\n document.body.appendChild(input);\n input.value = value;\n input.focus();\n input.select();\n const result = document.execCommand('copy');\n\n // @ts-expect-error -- The return type of `execCommand` can also be string\n if (result === 'unsuccessful') {\n throw new Error('Unable to copy value', { cause: result });\n }\n input.remove();\n\n return;\n }\n\n onCopy?.(value);\n setCopied(true);\n }, [onCopy, value]);\n\n const handleBlur: FocusEventHandler<HTMLButtonElement> = (event) => {\n if (copied) {\n setCopied(false);\n }\n\n onBlur?.(event);\n };\n\n return (\n <Tooltip\n content={copied ? tooltipCopiedText : tooltipText}\n {...tooltipProps}\n isDisabled={isDisabled}\n >\n <Button\n aria-label={copied ? tooltipCopiedText : label ?? tooltipText}\n aria-live=\"assertive\"\n className={cx(styles.button, className)}\n isDisabled={isLoading || isDisabled}\n isLoading={isLoading}\n onBlur={handleBlur}\n testId={testId}\n startIcon={\n <CopySimpleIcon\n color={tokens.gray600}\n size={size === 'small' ? 'tiny' : 'small'}\n />\n }\n variant=\"secondary\"\n {...otherProps}\n onClick={handleClick}\n ref={ref}\n />\n </Tooltip>\n );\n}\n\n_CopyButton.displayName = 'CopyButton';\n\nexport const CopyButton = React.forwardRef(_CopyButton);\n","import { css } from 'emotion';\nimport { CopyButtonProps } from './CopyButton';\n\nexport const getCopyButtonStyles = ({\n size,\n}: Pick<CopyButtonProps, 'size'>) => {\n const buttonSize = size === 'small' ? '32px' : '40px';\n\n return {\n button: css({\n height: buttonSize,\n minWidth: 'auto',\n width: buttonSize,\n\n 'span:first-child': { marginRight: 0 },\n }),\n };\n};\n"]}
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { TooltipProps } from '@contentful/f36-tooltip';
3
+ import { ButtonProps } from '@contentful/f36-button';
4
+
5
+ declare type CopyButtonProps = Omit<ButtonProps, 'endIcon' | 'onCopy' | 'onClick' | 'isDisabled' | 'size' | 'value'> & {
6
+ /**
7
+ * Function that gets called when the button is clicked
8
+ */
9
+ onCopy?: (string: any) => void;
10
+ /**
11
+ * Text to be shown when the button is clicked
12
+ * @default Copied!
13
+ */
14
+ tooltipCopiedText?: string;
15
+ /**
16
+ * Text to be shown when button is hovered or focused
17
+ * @default Copy to clipboard
18
+ */
19
+ tooltipText?: string;
20
+ /**
21
+ * Props that are passed to the tooltip component
22
+ */
23
+ tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;
24
+ /**
25
+ * Label to be used on aria-label for the button
26
+ * @default Copy to clipboard
27
+ */
28
+ label?: string;
29
+ /**
30
+ * Allows to disable the copy button, when true the tooltip would not be shown
31
+ * @default false
32
+ */
33
+ isDisabled?: boolean;
34
+ /**
35
+ * Allows setting size of the copy button to small
36
+ * @default medium
37
+ */
38
+ size?: 'small' | 'medium';
39
+ /**
40
+ * Value that will be copied to clipboard when the button is clicked
41
+ */
42
+ value: string;
43
+ };
44
+ declare const CopyButton: React.ForwardRefExoticComponent<Omit<ButtonProps<"button">, "size" | "isDisabled" | "endIcon" | "value" | "onCopy" | "onClick"> & {
45
+ /**
46
+ * Function that gets called when the button is clicked
47
+ */
48
+ onCopy?: (string: any) => void;
49
+ /**
50
+ * Text to be shown when the button is clicked
51
+ * @default Copied!
52
+ */
53
+ tooltipCopiedText?: string;
54
+ /**
55
+ * Text to be shown when button is hovered or focused
56
+ * @default Copy to clipboard
57
+ */
58
+ tooltipText?: string;
59
+ /**
60
+ * Props that are passed to the tooltip component
61
+ */
62
+ tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;
63
+ /**
64
+ * Label to be used on aria-label for the button
65
+ * @default Copy to clipboard
66
+ */
67
+ label?: string;
68
+ /**
69
+ * Allows to disable the copy button, when true the tooltip would not be shown
70
+ * @default false
71
+ */
72
+ isDisabled?: boolean;
73
+ /**
74
+ * Allows setting size of the copy button to small
75
+ * @default medium
76
+ */
77
+ size?: 'small' | 'medium';
78
+ /**
79
+ * Value that will be copied to clipboard when the button is clicked
80
+ */
81
+ value: string;
82
+ } & React.RefAttributes<HTMLButtonElement>>;
83
+
84
+ export { CopyButton, CopyButtonProps };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { CommonProps } from '@contentful/f36-core';
3
2
  import { TooltipProps } from '@contentful/f36-tooltip';
3
+ import { ButtonProps } from '@contentful/f36-button';
4
4
 
5
- interface CopyButtonProps extends CommonProps {
5
+ declare type CopyButtonProps = Omit<ButtonProps, 'endIcon' | 'onCopy' | 'onClick' | 'isDisabled' | 'size' | 'value'> & {
6
6
  /**
7
7
  * Function that gets called when the button is clicked
8
8
  */
@@ -21,13 +21,48 @@ interface CopyButtonProps extends CommonProps {
21
21
  * Props that are passed to the tooltip component
22
22
  */
23
23
  tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;
24
+ /**
25
+ * Label to be used on aria-label for the button
26
+ * @default Copy to clipboard
27
+ */
28
+ label?: string;
29
+ /**
30
+ * Allows to disable the copy button, when true the tooltip would not be shown
31
+ * @default false
32
+ */
33
+ isDisabled?: boolean;
34
+ /**
35
+ * Allows setting size of the copy button to small
36
+ * @default medium
37
+ */
38
+ size?: 'small' | 'medium';
24
39
  /**
25
40
  * Value that will be copied to clipboard when the button is clicked
26
41
  */
27
42
  value: string;
43
+ };
44
+ declare const CopyButton: React.ForwardRefExoticComponent<Omit<ButtonProps<"button">, "size" | "isDisabled" | "endIcon" | "value" | "onCopy" | "onClick"> & {
45
+ /**
46
+ * Function that gets called when the button is clicked
47
+ */
48
+ onCopy?: (string: any) => void;
49
+ /**
50
+ * Text to be shown when the button is clicked
51
+ * @default Copied!
52
+ */
53
+ tooltipCopiedText?: string;
54
+ /**
55
+ * Text to be shown when button is hovered or focused
56
+ * @default Copy to clipboard
57
+ */
58
+ tooltipText?: string;
59
+ /**
60
+ * Props that are passed to the tooltip component
61
+ */
62
+ tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;
28
63
  /**
29
64
  * Label to be used on aria-label for the button
30
- * @default Copy {value} to clipboard
65
+ * @default Copy to clipboard
31
66
  */
32
67
  label?: string;
33
68
  /**
@@ -40,7 +75,10 @@ interface CopyButtonProps extends CommonProps {
40
75
  * @default medium
41
76
  */
42
77
  size?: 'small' | 'medium';
43
- }
44
- declare const CopyButton: React.ForwardRefExoticComponent<CopyButtonProps & React.RefAttributes<HTMLDivElement>>;
78
+ /**
79
+ * Value that will be copied to clipboard when the button is clicked
80
+ */
81
+ value: string;
82
+ } & React.RefAttributes<HTMLButtonElement>>;
45
83
 
46
84
  export { CopyButton, CopyButtonProps };
package/dist/index.js CHANGED
@@ -1,21 +1,19 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var emotion = require('emotion');
6
- var n = require('react');
7
- var j = require('react-copy-to-clipboard');
3
+ var d = require('react');
4
+ var V = require('@contentful/f36-tokens');
8
5
  var f36Icons = require('@contentful/f36-icons');
9
6
  var f36Tooltip = require('@contentful/f36-tooltip');
10
- var i = require('@contentful/f36-tokens');
7
+ var f36Button = require('@contentful/f36-button');
8
+ var emotion = require('emotion');
11
9
 
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
11
 
14
- var n__default = /*#__PURE__*/_interopDefaultLegacy(n);
15
- var j__default = /*#__PURE__*/_interopDefaultLegacy(j);
16
- var i__default = /*#__PURE__*/_interopDefaultLegacy(i);
12
+ var d__default = /*#__PURE__*/_interopDefault(d);
13
+ var V__default = /*#__PURE__*/_interopDefault(V);
17
14
 
18
- var N=Object.defineProperty,$=Object.defineProperties;var I=Object.getOwnPropertyDescriptors;var s=Object.getOwnPropertySymbols;var f=Object.prototype.hasOwnProperty,C=Object.prototype.propertyIsEnumerable;var b=(o,t,e)=>t in o?N(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,u=(o,t)=>{for(var e in t||(t={}))f.call(t,e)&&b(o,e,t[e]);if(s)for(var e of s(t))C.call(t,e)&&b(o,e,t[e]);return o},g=(o,t)=>$(o,I(t));var x=(o,t)=>{var e={};for(var r in o)f.call(o,r)&&t.indexOf(r)<0&&(e[r]=o[r]);if(o!=null&&s)for(var r of s(o))t.indexOf(r)<0&&C.call(o,r)&&(e[r]=o[r]);return e};var h=({size:o})=>{let t=o==="small"?"32px":"40px";return {wrapper:emotion.css({display:"inline-block",height:t,position:"relative",width:t}),copyButton:emotion.css({alignItems:"center",background:i__default["default"].colorWhite,border:`1px solid ${i__default["default"].gray300}`,display:"inline-flex",height:"100%",justifyContent:"center",outline:"none",padding:0,transition:`background ${i__default["default"].transitionDurationShort} ${i__default["default"].transitionEasingDefault}`,width:"100%","&:hover":{backgroundColor:i__default["default"].gray100,cursor:"pointer"},"&:active":{backgroundColor:i__default["default"].gray200,cursor:"pointer"},"&:focus":{boxShadow:i__default["default"].glowMuted},"&:focus:not(:focus-visible)":{boxShadow:"unset"},"&:focus-visible":{boxShadow:i__default["default"].glowMuted}}),copyButtonDisabled:emotion.css({cursor:"not-allowed",backgroundColor:i__default["default"].gray100,"&:hover":{cursor:"not-allowed",backgroundColor:i__default["default"].gray100},"&:focus":{borderColor:i__default["default"].gray300,boxShadow:"none"},"&:active, &:active:hover":{borderColor:i__default["default"].gray300,boxShadow:"none"}})}};function w(o,t){let y=o,{onCopy:e,value:r,className:B,testId:T="cf-ui-copy-button",tooltipText:P="Copy to clipboard",tooltipCopiedText:S="Copied!",tooltipProps:k,isDisabled:p=!1,size:c="medium"}=y,D=x(y,["onCopy","value","className","testId","tooltipText","tooltipCopiedText","tooltipProps","isDisabled","size"]),l=h({size:c}),[E,m]=n.useState(!1),a=n.useRef(null),z=n.useCallback(M=>{e&&e(M),m(!0),setTimeout(()=>{m(!1),a.current&&a.current.blur();},1e3);},[e]);return n__default["default"].createElement("div",u({ref:t,"data-test-id":T,className:emotion.cx(l.wrapper,B)},D),n__default["default"].createElement(j__default["default"],{text:r,onCopy:z},n__default["default"].createElement(f36Tooltip.Tooltip,g(u({content:E?S:P},k),{isDisabled:p}),n__default["default"].createElement("button",{type:"button",ref:a,className:emotion.cx(l.copyButton,{[l.copyButtonDisabled]:p}),"aria-label":`Copy ${r} to clipboard`,disabled:p,"aria-live":"assertive"},n__default["default"].createElement(f36Icons.CopyIcon,{variant:"muted",size:c==="small"?"tiny":"small"})))))}w.displayName="CopyButton";var q=n__default["default"].forwardRef(w);
15
+ var L=Object.defineProperty,F=Object.defineProperties;var N=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,E=Object.prototype.propertyIsEnumerable;var x=(t,o,e)=>o in t?L(t,o,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[o]=e,f=(t,o)=>{for(var e in o||(o={}))v.call(o,e)&&x(t,e,o[e]);if(m)for(var e of m(o))E.call(o,e)&&x(t,e,o[e]);return t},C=(t,o)=>F(t,N(o));var w=(t,o)=>{var e={};for(var n in t)v.call(t,n)&&o.indexOf(n)<0&&(e[n]=t[n]);if(t!=null&&m)for(var n of m(t))o.indexOf(n)<0&&E.call(t,n)&&(e[n]=t[n]);return e};var T=(t,o,e)=>new Promise((n,s)=>{var i=r=>{try{a(e.next(r));}catch(l){s(l);}},c=r=>{try{a(e.throw(r));}catch(l){s(l);}},a=r=>r.done?n(r.value):Promise.resolve(r.value).then(i,c);a((e=e.apply(t,o)).next());});var H=({size:t})=>{let o=t==="small"?"32px":"40px";return {button:emotion.css({height:o,minWidth:"auto",width:o,"span:first-child":{marginRight:0}})}};function k(G,S){var P=G,{className:t,isDisabled:o=!1,isLoading:e=!1,label:n,onBlur:s,onCopy:i,size:c="medium",testId:a="cf-ui-copy-button",tooltipCopiedText:r="Value copied to clipboard",tooltipProps:l,tooltipText:B="Copy to clipboard",value:u}=P,M=w(P,["className","isDisabled","isLoading","label","onBlur","onCopy","size","testId","tooltipCopiedText","tooltipProps","tooltipText","value"]);let z=H({size:c}),[y,b]=d.useState(!1),I=d.useCallback(()=>T(this,null,function*(){try{yield window.navigator.clipboard.writeText(u);}catch(g){let p=document.createElement("input");p.style.display="none",document.body.appendChild(p),p.value=u,p.focus(),p.select();let h=document.execCommand("copy");if(h==="unsuccessful")throw new Error("Unable to copy value",{cause:h});p.remove();return}i==null||i(u),b(!0);}),[i,u]),D=g=>{y&&b(!1),s==null||s(g);};return d__default.default.createElement(f36Tooltip.Tooltip,C(f({content:y?r:B},l),{isDisabled:o}),d__default.default.createElement(f36Button.Button,C(f({"aria-label":y?r:n!=null?n:B,"aria-live":"assertive",className:emotion.cx(z.button,t),isDisabled:e||o,isLoading:e,onBlur:D,testId:a,startIcon:d__default.default.createElement(f36Icons.CopySimpleIcon,{color:V__default.default.gray600,size:c==="small"?"tiny":"small"}),variant:"secondary"},M),{onClick:I,ref:S})))}k.displayName="CopyButton";var A=d__default.default.forwardRef(k);
19
16
 
20
- exports.CopyButton = q;
17
+ exports.CopyButton = A;
18
+ //# sourceMappingURL=out.js.map
21
19
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/CopyButton.tsx","../src/CopyButton.styles.ts"],"names":["cx","React","useState","useCallback","useRef","CopyToClipboard","CopyIcon","Tooltip","css","tokens","getStyles","size","buttonSize","_CopyButton","props","ref","_a","onCopy","value","className","testId","tooltipText","tooltipCopiedText","tooltipProps","isDisabled","otherProps","__objRest","styles","copied","setCopied","button","handleOnCopy","e","__spreadValues","__spreadProps","CopyButton"],"mappings":"+kBAAA,OAAS,MAAAA,MAAU,UACnB,OAAOC,GAAS,YAAAC,EAAU,eAAAC,EAAa,UAAAC,MAAc,QACrD,OAAOC,MAAqB,0BAC5B,OAAS,YAAAC,MAAgB,wBAEzB,OAAS,WAAAC,MAAkC,0BCL3C,OAAS,OAAAC,MAAW,UACpB,OAAOC,MAAY,yBAEZ,IAAMC,EAAY,CAAC,CAAE,KAAAC,CAAK,IAAM,CACrC,IAAMC,EAAaD,IAAS,QAAU,OAAS,OAE/C,MAAO,CACL,QAASH,EAAI,CACX,QAAS,eACT,OAAQI,EACR,SAAU,WACV,MAAOA,CACT,CAAC,EACD,WAAYJ,EAAI,CACd,WAAY,SACZ,WAAYC,EAAO,WACnB,OAAQ,aAAaA,EAAO,UAC5B,QAAS,cACT,OAAQ,OACR,eAAgB,SAChB,QAAS,OACT,QAAS,EACT,WAAY,cAAcA,EAAO,2BAA2BA,EAAO,0BACnE,MAAO,OACP,UAAW,CACT,gBAAiBA,EAAO,QACxB,OAAQ,SACV,EACA,WAAY,CACV,gBAAiBA,EAAO,QACxB,OAAQ,SACV,EACA,UAAW,CACT,UAAWA,EAAO,SACpB,EACA,8BAA+B,CAC7B,UAAW,OACb,EACA,kBAAmB,CACjB,UAAWA,EAAO,SACpB,CACF,CAAC,EACD,mBAAoBD,EAAI,CACtB,OAAQ,cACR,gBAAiBC,EAAO,QAExB,UAAW,CACT,OAAQ,cACR,gBAAiBA,EAAO,OAC1B,EAEA,UAAW,CACT,YAAaA,EAAO,QACpB,UAAW,MACb,EAEA,2BAA4B,CAC1B,YAAaA,EAAO,QACpB,UAAW,MACb,CACF,CAAC,CACH,CACF,EDdA,SAASI,EACPC,EACAC,EACA,CACA,IAWIC,EAAAF,EAVF,QAAAG,EACA,MAAAC,EACA,UAAAC,EACA,OAAAC,EAAS,oBACT,YAAAC,EAAc,oBACd,kBAAAC,EAAoB,UACpB,aAAAC,EACA,WAAAC,EAAa,GACb,KAAAb,EAAO,QA7DX,EA+DMK,EADCS,EAAAC,EACDV,EADC,CATH,SACA,QACA,YACA,SACA,cACA,oBACA,eACA,aACA,SAGIW,EAASjB,EAAU,CAAE,KAAAC,CAAK,CAAC,EAE3B,CAACiB,EAAQC,CAAS,EAAI3B,EAAS,EAAK,EACpC4B,EAAS1B,EAAiC,IAAI,EAC9C2B,EAAe5B,EAClB6B,GAAc,CACTf,GACFA,EAAOe,CAAC,EAGVH,EAAU,EAAI,EAEd,WAAW,IAAM,CACfA,EAAU,EAAK,EACXC,EAAO,SACTA,EAAO,QAAQ,KAAK,CAExB,EAAG,GAAI,CACT,EACA,CAACb,CAAM,CACT,EAEA,OACEhB,EAAA,cAAC,MAAAgC,EAAA,CACC,IAAKlB,EACL,eAAcK,EACd,UAAWpB,EAAG2B,EAAO,QAASR,CAAS,GACnCM,GAEJxB,EAAA,cAACI,EAAA,CAAgB,KAAMa,EAAO,OAAQa,GACpC9B,EAAA,cAACM,EAAA2B,EAAAD,EAAA,CACC,QAASL,EAASN,EAAoBD,GAClCE,GAFL,CAGC,WAAYC,IAEZvB,EAAA,cAAC,UACC,KAAK,SACL,IAAK6B,EACL,UAAW9B,EAAG2B,EAAO,WAAY,CAC/B,CAACA,EAAO,oBAAqBH,CAC/B,CAAC,EACD,aAAY,QAAQN,iBACpB,SAAUM,EACV,YAAU,aAEVvB,EAAA,cAACK,EAAA,CACC,QAAQ,QACR,KAAMK,IAAS,QAAU,OAAS,QACpC,CACF,CACF,CACF,CACF,CAEJ,CAEAE,EAAY,YAAc,aAEnB,IAAMsB,EAAalC,EAAM,WAAWY,CAAW","sourcesContent":["import { cx } from 'emotion';\nimport React, { useState, useCallback, useRef } from 'react';\nimport CopyToClipboard from 'react-copy-to-clipboard';\nimport { CopyIcon } from '@contentful/f36-icons';\nimport type { CommonProps, ExpandProps } from '@contentful/f36-core';\nimport { Tooltip, type TooltipProps } from '@contentful/f36-tooltip';\nimport { getStyles } from './CopyButton.styles';\n\nexport interface CopyButtonProps extends CommonProps {\n /**\n * Function that gets called when the button is clicked\n */\n onCopy?: (string) => void;\n /**\n * Text to be shown when the button is clicked\n * @default Copied!\n */\n tooltipCopiedText?: string;\n /**\n * Text to be shown when button is hovered or focused\n * @default Copy to clipboard\n */\n tooltipText?: string;\n /**\n * Props that are passed to the tooltip component\n */\n tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;\n /**\n * Value that will be copied to clipboard when the button is clicked\n */\n value: string;\n /**\n * Label to be used on aria-label for the button\n * @default Copy {value} to clipboard\n */\n label?: string;\n /**\n * Allows to disable the copy button, when true the tooltip would not be shown\n * @default false\n */\n isDisabled?: boolean;\n /**\n * Allows setting size of the copy button to small\n * @default medium\n */\n size?: 'small' | 'medium';\n}\n\nfunction _CopyButton(\n props: ExpandProps<CopyButtonProps>,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {\n onCopy,\n value,\n className,\n testId = 'cf-ui-copy-button',\n tooltipText = 'Copy to clipboard',\n tooltipCopiedText = 'Copied!',\n tooltipProps,\n isDisabled = false,\n size = 'medium',\n ...otherProps\n } = props;\n const styles = getStyles({ size });\n\n const [copied, setCopied] = useState(false);\n const button = useRef<HTMLButtonElement | null>(null);\n const handleOnCopy = useCallback(\n (e: string) => {\n if (onCopy) {\n onCopy(e);\n }\n\n setCopied(true);\n\n setTimeout(() => {\n setCopied(false);\n if (button.current) {\n button.current.blur();\n }\n }, 1000);\n },\n [onCopy],\n );\n\n return (\n <div\n ref={ref}\n data-test-id={testId}\n className={cx(styles.wrapper, className)}\n {...otherProps}\n >\n <CopyToClipboard text={value} onCopy={handleOnCopy}>\n <Tooltip\n content={copied ? tooltipCopiedText : tooltipText}\n {...tooltipProps}\n isDisabled={isDisabled}\n >\n <button\n type=\"button\"\n ref={button}\n className={cx(styles.copyButton, {\n [styles.copyButtonDisabled]: isDisabled,\n })}\n aria-label={`Copy ${value} to clipboard`}\n disabled={isDisabled}\n aria-live=\"assertive\"\n >\n <CopyIcon\n variant=\"muted\"\n size={size === 'small' ? 'tiny' : 'small'}\n />\n </button>\n </Tooltip>\n </CopyToClipboard>\n </div>\n );\n}\n\n_CopyButton.displayName = 'CopyButton';\n\nexport const CopyButton = React.forwardRef(_CopyButton);\n","import { css } from 'emotion';\nimport tokens from '@contentful/f36-tokens';\n\nexport const getStyles = ({ size }) => {\n const buttonSize = size === 'small' ? '32px' : '40px';\n\n return {\n wrapper: css({\n display: 'inline-block',\n height: buttonSize,\n position: 'relative',\n width: buttonSize,\n }),\n copyButton: css({\n alignItems: 'center',\n background: tokens.colorWhite,\n border: `1px solid ${tokens.gray300}`,\n display: 'inline-flex',\n height: '100%',\n justifyContent: 'center',\n outline: 'none',\n padding: 0,\n transition: `background ${tokens.transitionDurationShort} ${tokens.transitionEasingDefault}`,\n width: '100%',\n '&:hover': {\n backgroundColor: tokens.gray100,\n cursor: 'pointer',\n },\n '&:active': {\n backgroundColor: tokens.gray200,\n cursor: 'pointer',\n },\n '&:focus': {\n boxShadow: tokens.glowMuted,\n },\n '&:focus:not(:focus-visible)': {\n boxShadow: 'unset',\n },\n '&:focus-visible': {\n boxShadow: tokens.glowMuted,\n },\n }),\n copyButtonDisabled: css({\n cursor: 'not-allowed',\n backgroundColor: tokens.gray100,\n\n '&:hover': {\n cursor: 'not-allowed',\n backgroundColor: tokens.gray100,\n },\n\n '&:focus': {\n borderColor: tokens.gray300,\n boxShadow: 'none',\n },\n\n '&:active, &:active:hover': {\n borderColor: tokens.gray300,\n boxShadow: 'none',\n },\n }),\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/CopyButton.tsx","../src/CopyButton.styles.ts"],"names":["React","useCallback","useState","tokens","CopySimpleIcon","Tooltip","Button","css","getCopyButtonStyles","size","buttonSize","cx","_CopyButton","_a","ref","_b","className","isDisabled","isLoading","label","onBlur","onCopy","testId","tooltipCopiedText","tooltipProps","tooltipText","value","otherProps","__objRest","styles","copied","setCopied","handleClick","__async","error","input","result","handleBlur","event","__spreadProps","__spreadValues","CopyButton"],"mappings":"4xBAAA,OAAOA,GACL,eAAAC,EACA,YAAAC,MAGK,QACP,OAAOC,MAAY,yBACnB,OAAS,kBAAAC,MAAsB,wBAE/B,OAAS,WAAAC,MAAkC,0BAC3C,OAAS,UAAAC,MAAgC,yBCVzC,OAAS,OAAAC,MAAW,UAGb,IAAMC,EAAsB,CAAC,CAClC,KAAAC,CACF,IAAqC,CACnC,IAAMC,EAAaD,IAAS,QAAU,OAAS,OAE/C,MAAO,CACL,OAAQF,EAAI,CACV,OAAQG,EACR,SAAU,OACV,MAAOA,EAEP,mBAAoB,CAAE,YAAa,CAAE,CACvC,CAAC,CACH,CACF,EDLA,OAAS,MAAAC,MAAU,UA6CnB,SAASC,EACPC,EAeAC,EACA,CAhBA,IAAAC,EAAAF,EACE,WAAAG,EACA,WAAAC,EAAa,GACb,UAAAC,EAAY,GACZ,MAAAC,EACA,OAAAC,EACA,OAAAC,EACA,KAAAZ,EAAO,SACP,OAAAa,EAAS,oBACT,kBAAAC,EAAoB,4BACpB,aAAAC,EACA,YAAAC,EAAc,oBACd,MAAAC,CAtEJ,EA0DEX,EAaKY,EAAAC,EAbLb,EAaK,CAZH,YACA,aACA,YACA,QACA,SACA,SACA,OACA,SACA,oBACA,eACA,cACA,UAKF,IAAMc,EAASrB,EAAoB,CAAE,KAAAC,CAAK,CAAC,EACrC,CAACqB,EAAQC,CAAS,EAAI7B,EAAS,EAAK,EAEpC8B,EAAc/B,EAElB,IAAYgC,EAAA,sBACZ,GAAI,CACF,MAAM,OAAO,UAAU,UAAU,UAAUP,CAAK,CAClD,OAASQ,EAAO,CAGd,IAAMC,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,MAAM,QAAU,OACtB,SAAS,KAAK,YAAYA,CAAK,EAC/BA,EAAM,MAAQT,EACdS,EAAM,MAAM,EACZA,EAAM,OAAO,EACb,IAAMC,EAAS,SAAS,YAAY,MAAM,EAG1C,GAAIA,IAAW,eACb,MAAM,IAAI,MAAM,uBAAwB,CAAE,MAAOA,CAAO,CAAC,EAE3DD,EAAM,OAAO,EAEb,MACF,CAEAd,GAAA,MAAAA,EAASK,GACTK,EAAU,EAAI,CAChB,GAAG,CAACV,EAAQK,CAAK,CAAC,EAEZW,EAAoDC,GAAU,CAC9DR,GACFC,EAAU,EAAK,EAGjBX,GAAA,MAAAA,EAASkB,EACX,EAEA,OACEtC,EAAA,cAACK,EAAAkC,EAAAC,EAAA,CACC,QAASV,EAASP,EAAoBE,GAClCD,GAFL,CAGC,WAAYP,IAEZjB,EAAA,cAACM,EAAAiC,EAAAC,EAAA,CACC,aAAYV,EAASP,EAAoBJ,GAAA,KAAAA,EAASM,EAClD,YAAU,YACV,UAAWd,EAAGkB,EAAO,OAAQb,CAAS,EACtC,WAAYE,GAAaD,EACzB,UAAWC,EACX,OAAQmB,EACR,OAAQf,EACR,UACEtB,EAAA,cAACI,EAAA,CACC,MAAOD,EAAO,QACd,KAAMM,IAAS,QAAU,OAAS,QACpC,EAEF,QAAQ,aACJkB,GAfL,CAgBC,QAASK,EACT,IAAKlB,GACP,CACF,CAEJ,CAEAF,EAAY,YAAc,aAEnB,IAAM6B,EAAazC,EAAM,WAAWY,CAAW","sourcesContent":["import React, {\n useCallback,\n useState,\n type MouseEventHandler,\n type FocusEventHandler,\n} from 'react';\nimport tokens from '@contentful/f36-tokens';\nimport { CopySimpleIcon } from '@contentful/f36-icons';\nimport type { ExpandProps } from '@contentful/f36-core';\nimport { Tooltip, type TooltipProps } from '@contentful/f36-tooltip';\nimport { Button, type ButtonProps } from '@contentful/f36-button';\nimport { getCopyButtonStyles } from './CopyButton.styles';\nimport { cx } from 'emotion';\n\nexport type CopyButtonProps = Omit<\n ButtonProps,\n 'endIcon' | 'onCopy' | 'onClick' | 'isDisabled' | 'size' | 'value'\n> & {\n /**\n * Function that gets called when the button is clicked\n */\n onCopy?: (string) => void;\n /**\n * Text to be shown when the button is clicked\n * @default Copied!\n */\n tooltipCopiedText?: string;\n /**\n * Text to be shown when button is hovered or focused\n * @default Copy to clipboard\n */\n tooltipText?: string;\n /**\n * Props that are passed to the tooltip component\n */\n tooltipProps?: Omit<TooltipProps, 'content' | 'children'>;\n /**\n * Label to be used on aria-label for the button\n * @default Copy to clipboard\n */\n label?: string;\n /**\n * Allows to disable the copy button, when true the tooltip would not be shown\n * @default false\n */\n isDisabled?: boolean;\n /**\n * Allows setting size of the copy button to small\n * @default medium\n */\n size?: 'small' | 'medium';\n /**\n * Value that will be copied to clipboard when the button is clicked\n */\n value: string;\n};\n\nfunction _CopyButton(\n {\n className,\n isDisabled = false,\n isLoading = false,\n label,\n onBlur,\n onCopy,\n size = 'medium',\n testId = 'cf-ui-copy-button',\n tooltipCopiedText = 'Value copied to clipboard',\n tooltipProps,\n tooltipText = 'Copy to clipboard',\n value,\n ...otherProps\n }: ExpandProps<CopyButtonProps>,\n ref: React.Ref<HTMLButtonElement>,\n) {\n const styles = getCopyButtonStyles({ size });\n const [copied, setCopied] = useState(false);\n\n const handleClick = useCallback<\n MouseEventHandler<HTMLButtonElement>\n >(async () => {\n try {\n await window.navigator.clipboard.writeText(value);\n } catch (error) {\n // Chrome requires specific permissions on iframes using the async clipboard\n // API. We can't control that so we fall back to this\n const input = document.createElement('input');\n input.style.display = 'none';\n document.body.appendChild(input);\n input.value = value;\n input.focus();\n input.select();\n const result = document.execCommand('copy');\n\n // @ts-expect-error -- The return type of `execCommand` can also be string\n if (result === 'unsuccessful') {\n throw new Error('Unable to copy value', { cause: result });\n }\n input.remove();\n\n return;\n }\n\n onCopy?.(value);\n setCopied(true);\n }, [onCopy, value]);\n\n const handleBlur: FocusEventHandler<HTMLButtonElement> = (event) => {\n if (copied) {\n setCopied(false);\n }\n\n onBlur?.(event);\n };\n\n return (\n <Tooltip\n content={copied ? tooltipCopiedText : tooltipText}\n {...tooltipProps}\n isDisabled={isDisabled}\n >\n <Button\n aria-label={copied ? tooltipCopiedText : label ?? tooltipText}\n aria-live=\"assertive\"\n className={cx(styles.button, className)}\n isDisabled={isLoading || isDisabled}\n isLoading={isLoading}\n onBlur={handleBlur}\n testId={testId}\n startIcon={\n <CopySimpleIcon\n color={tokens.gray600}\n size={size === 'small' ? 'tiny' : 'small'}\n />\n }\n variant=\"secondary\"\n {...otherProps}\n onClick={handleClick}\n ref={ref}\n />\n </Tooltip>\n );\n}\n\n_CopyButton.displayName = 'CopyButton';\n\nexport const CopyButton = React.forwardRef(_CopyButton);\n","import { css } from 'emotion';\nimport { CopyButtonProps } from './CopyButton';\n\nexport const getCopyButtonStyles = ({\n size,\n}: Pick<CopyButtonProps, 'size'>) => {\n const buttonSize = size === 'small' ? '32px' : '40px';\n\n return {\n button: css({\n height: buttonSize,\n minWidth: 'auto',\n width: buttonSize,\n\n 'span:first-child': { marginRight: 0 },\n }),\n };\n};\n"]}
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "@contentful/f36-copybutton",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Forma 36: CopyButton component",
5
5
  "scripts": {
6
6
  "build": "tsup"
7
7
  },
8
8
  "dependencies": {
9
- "@contentful/f36-core": "^5.0.0",
10
- "@contentful/f36-icons": "^5.0.0",
11
- "@contentful/f36-tokens": "^4.0.1",
12
- "@contentful/f36-tooltip": "^5.0.0",
13
- "emotion": "^10.0.17",
14
- "react-copy-to-clipboard": "^5.1.0"
9
+ "@contentful/f36-button": "^5.1.0",
10
+ "@contentful/f36-core": "^5.1.0",
11
+ "@contentful/f36-icons": "^5.1.0",
12
+ "@contentful/f36-tokens": "^5.1.0",
13
+ "@contentful/f36-tooltip": "^5.1.0",
14
+ "emotion": "^10.0.17"
15
15
  },
16
16
  "peerDependencies": {
17
- "react": ">=16.8"
17
+ "react": ">=16.8",
18
+ "react-dom": ">=16.8"
18
19
  },
19
20
  "license": "MIT",
20
21
  "files": [
@@ -28,9 +29,10 @@
28
29
  "browserslist": "extends @contentful/browserslist-config",
29
30
  "repository": {
30
31
  "type": "git",
31
- "url": "https://github.com/contentful/forma-36"
32
+ "url": "git+https://github.com/contentful/forma-36.git"
32
33
  },
33
34
  "publishConfig": {
35
+ "registry": "https://npm.pkg.github.com/",
34
36
  "access": "public"
35
37
  }
36
38
  }