apple-pay-button
Version:
Apple Pay Button built in React following Apple Pay Button JavaScript guidelines
1 lines • 6.41 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import type { ElementRef, RefObject } from 'react';\nimport React, { useEffect, useRef } from 'react';\n\ntype ButtonType =\n | 'plain'\n | 'add-money'\n | 'book'\n | 'buy'\n | 'check-out'\n | 'continue'\n | 'contribute'\n | 'donate'\n | 'order'\n | 'pay'\n | 'reload'\n | 'rent'\n | 'set-up'\n | 'subscribe'\n | 'support'\n | 'tip'\n | 'top-up';\n\nexport interface ApplePayButtonProps {\n buttonStyle?: 'black' | 'white' | 'white-outline';\n type?: ButtonType;\n locale?: string;\n onClick?: () => void;\n style?: {\n width?: string;\n height?: string;\n borderRadius?: string;\n padding?: string;\n boxSizing?: string;\n };\n disabled?: boolean;\n}\n\nconst ApplePayButton: React.FC<ApplePayButtonProps> = ({\n buttonStyle = 'black',\n type = 'buy',\n locale = 'en-US',\n onClick,\n style,\n disabled\n}) => {\n const buttonRef = useRef<ElementRef<'div'>>(null);\n\n const handleClick = (): void => {\n if (disabled !== true && onClick !== undefined) {\n onClick();\n }\n };\n\n useEffect(() => {\n const scriptId = 'apple-pay-sdk-script';\n const applePayScriptSrc =\n 'https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js';\n\n if (document.getElementById(scriptId) !== null) {\n return;\n }\n\n const script = document.createElement('script');\n script.id = scriptId;\n script.src = applePayScriptSrc;\n script.async = true;\n document.body.appendChild(script);\n }, []);\n\n useEffect(() => {\n if (buttonRef.current !== null) {\n buttonRef.current.addEventListener('click', handleClick);\n }\n\n return () => {\n if (buttonRef.current !== null) {\n buttonRef.current.removeEventListener('click', handleClick);\n }\n };\n }, [onClick, disabled]);\n\n const updateButtonStyle = (\n button?: Element | null,\n disabled?: boolean\n ): void => {\n const cursor = disabled === true ? 'not-allowed' : 'pointer';\n const opacity = disabled === true ? '0.5' : '1';\n button?.setAttribute('style', `cursor: ${cursor}; opacity: ${opacity};`);\n };\n\n useEffect(() => {\n // This workaround modifies the cursor and opacity of the button. Due to the button being rendered in a Shadow DOM,\n // we face limitations with CSS and element attributes. Direct style application from the parent element,\n // or using pseudo-classes like :hover or :disabled, is not possible.\n if (\n buttonRef.current?.shadowRoot !== null ||\n buttonRef.current?.shadowRoot !== undefined\n ) {\n const button =\n buttonRef.current?.shadowRoot?.querySelector('div > button');\n updateButtonStyle(button, disabled);\n }\n }, [disabled, buttonRef.current?.shadowRoot]);\n\n const createApplePayButtonStyle = (\n style?: ApplePayButtonProps['style']\n ): string => `\n apple-pay-button {\n --apple-pay-button-width: ${style?.width ?? 'auto'};\n --apple-pay-button-height: ${style?.height ?? '30px'};\n --apple-pay-button-border-radius: ${style?.borderRadius ?? '5px'};\n --apple-pay-button-padding: ${style?.padding ?? '5px 0px'};\n --apple-pay-button-box-sizing: ${style?.boxSizing ?? 'border-box'};\n /* hide the button until the shadow root is available */\n display: ${\n buttonRef.current?.shadowRoot !== null ||\n buttonRef.current?.shadowRoot !== undefined\n ? 'inline-block'\n : 'none'\n };\n }\n`;\n\n const createApplePayButton = (\n buttonStyle: string,\n type: string,\n locale: string,\n buttonRef: RefObject<ElementRef<'div'>>\n ): React.ReactElement<\n {\n buttonstyle: string;\n type: string;\n locale: string;\n ref: RefObject<HTMLDivElement>;\n },\n string | React.JSXElementConstructor<'apple-pay-button'>\n > =>\n React.createElement('apple-pay-button', {\n buttonstyle: buttonStyle,\n type,\n locale,\n ref: buttonRef\n });\n\n return (\n <>\n {/* these CSS variables are used to style the button\n more details here https://applepaydemo.apple.com */}\n <style>{createApplePayButtonStyle(style)}</style>\n {/* <apple-pay-button> is not a valid JSX element\n so we need to use React.createElement() to render it\n and pass the props to it */}\n {createApplePayButton(buttonStyle, type, locale, buttonRef)}\n </>\n );\n};\n\nexport default ApplePayButton;\n"],"mappings":";AACA,OAAO,SAAS,WAAW,cAAc;AAoCzC,IAAM,iBAAgD,CAAC;AAAA,EACrD,cAAc;AAAA,EACd,OAAO;AAAA,EACP,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,MAAM;AA5CN;AA6CE,QAAM,YAAY,OAA0B,IAAI;AAEhD,QAAM,cAAc,MAAY;AAC9B,QAAI,aAAa,QAAQ,YAAY,QAAW;AAC9C,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,YAAU,MAAM;AACd,UAAM,WAAW;AACjB,UAAM,oBACJ;AAEF,QAAI,SAAS,eAAe,QAAQ,MAAM,MAAM;AAC9C;AAAA,IACF;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,UAAU,YAAY,MAAM;AAC9B,gBAAU,QAAQ,iBAAiB,SAAS,WAAW;AAAA,IACzD;AAEA,WAAO,MAAM;AACX,UAAI,UAAU,YAAY,MAAM;AAC9B,kBAAU,QAAQ,oBAAoB,SAAS,WAAW;AAAA,MAC5D;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,CAAC;AAEtB,QAAM,oBAAoB,CACxB,QACAA,cACS;AACT,UAAM,SAASA,cAAa,OAAO,gBAAgB;AACnD,UAAM,UAAUA,cAAa,OAAO,QAAQ;AAC5C,qCAAQ,aAAa,SAAS,WAAW,MAAM,cAAc,OAAO;AAAA,EACtE;AAEA,YAAU,MAAM;AA1FlB,QAAAC,KAAA;AA8FI,UACEA,MAAA,UAAU,YAAV,gBAAAA,IAAmB,gBAAe,UAClC,eAAU,YAAV,mBAAmB,gBAAe,QAClC;AACA,YAAM,UACJ,qBAAU,YAAV,mBAAmB,eAAnB,mBAA+B,cAAc;AAC/C,wBAAkB,QAAQ,QAAQ;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,WAAU,eAAU,YAAV,mBAAmB,UAAU,CAAC;AAE5C,QAAM,4BAA4B,CAChCC,WACQ;AA1GZ,QAAAD,KAAA;AA0Ge;AAAA;AAAA,qCAEqBA,MAAAC,UAAA,gBAAAA,OAAO,UAAP,OAAAD,MAAgB,MAAM;AAAA,sCACrB,KAAAC,UAAA,gBAAAA,OAAO,WAAP,YAAiB,MAAM;AAAA,6CAChB,KAAAA,UAAA,gBAAAA,OAAO,iBAAP,YAAuB,KAAK;AAAA,uCAClC,KAAAA,UAAA,gBAAAA,OAAO,YAAP,YAAkB,SAAS;AAAA,0CACxB,KAAAA,UAAA,gBAAAA,OAAO,cAAP,YAAoB,YAAY;AAAA;AAAA,qBAG/D,eAAU,YAAV,mBAAmB,gBAAe,UAClC,eAAU,YAAV,mBAAmB,gBAAe,SAC9B,iBACA,MACN;AAAA;AAAA;AAAA;AAIN,QAAM,uBAAuB,CAC3BC,cACAC,OACAC,SACAC,eAUA,MAAM,cAAc,oBAAoB;AAAA,IACtC,aAAaH;AAAA,IACb,MAAAC;AAAA,IACA,QAAAC;AAAA,IACA,KAAKC;AAAA,EACP,CAAC;AAEH,SACE,0DAGE,oCAAC,eAAO,0BAA0B,KAAK,CAAE,GAIxC,qBAAqB,aAAa,MAAM,QAAQ,SAAS,CAC5D;AAEJ;AAEA,IAAO,cAAQ;","names":["disabled","_a","style","buttonStyle","type","locale","buttonRef"]}