UNPKG

@alephium/web3-react

Version:
1,397 lines (1,338 loc) 261 kB
'use client'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import React, { createContext, useContext, useRef, useState, useEffect, useCallback, useLayoutEffect, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { createPortal } from 'react-dom'; import { detect } from 'detect-browser'; import styled$1, { keyframes, css, ThemeProvider } from 'styled-components'; import { useTransition } from 'react-transition-state'; import ResizeObserver from 'resize-observer-polyfill'; import useMeasure from 'react-use-measure'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; import { getDefaultAlephiumWallet, isWalletObj, getWalletObject, alephiumProvider, providerInitializedEvent } from '@alephium/get-extension-wallet'; import { isBalanceEqual, subscribeToTxStatus, web3 } from '@alephium/web3'; import { WalletConnectProvider, isCompatibleAddressGroup } from '@alephium/walletconnect-provider'; import QRCodeModal from '@alephium/walletconnect-qrcode-modal'; const defaultLightTheme = { font: { family: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, 'Apple Color Emoji', Arial, sans-serif, 'Segoe UI Emoji'` }, text: { primary: { color: '#373737' }, secondary: { color: '#999999', hover: { color: '#111111' } }, error: '#FC6464', valid: '#32D74B' }, buttons: { primary: { borderRadius: 16, color: '#000373737000', background: '#FFFFFF', border: '#F0F0F0', hover: { color: '#000000', border: '#1A88F8' } }, secondary: { borderRadius: 16, background: '#F6F7F9', color: '#000000' } }, navigation: { color: '#999999' }, modal: { background: '#ffffff', // need to generate an rgba transparent version of this for Safari divider: '#f7f6f8' }, tooltips: { color: '#999999', background: '#ffffff', hover: { background: '#f6f7f9' } }, overlay: { background: 'rgba(0, 0, 0, 0.06)' }, qrCode: { accentColor: '#F7F6F8' } }; // parse into css variables so we can use p3 colors const parseTheme = (theme) => { return theme; }; const userPrefersDarkMode = () => { if (typeof window === 'undefined') return false; return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; /* window .matchMedia('(prefers-color-scheme: dark)') .addEventListener('change', (event) => { userPrefersDarkMode = event.matches; }); */ }; userPrefersDarkMode(); const defaultTheme$1 = { connectKit: { options: { iconStyle: 'light' }, //theme: parseTheme(defaultLightTheme), theme: { preferred: 'dark', light: parseTheme(defaultLightTheme), dark: parseTheme(defaultLightTheme) } } }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ const ConnectSettingContext = createContext(null); const useConnectSettingContext = () => { const context = useContext(ConnectSettingContext); if (!context) throw Error('ConnectSetting Hook must be inside a Provider.'); return context; }; const AlephiumConnectContext = createContext(null); // Use hooks `useWallet` and `useWalletConfig` instead const useAlephiumConnectContext = () => { const context = useContext(AlephiumConnectContext); if (!context) throw Error('AlephiumConnect Hook must be inside a Provider.'); return context; }; const AlephiumBalanceContext = createContext(null); // Use hook `useBalance` instead const useAlephiumBalanceContext = () => { const context = useContext(AlephiumBalanceContext); if (!context) throw Error('AlephiumBalance Hook must be inside a Provider.'); return context; }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ const Portal = (props) => { props = { selector: '__ALEPHIUMCONNECT__', ...props }; const { selector, children } = props; const ref = useRef(null); const [mounted, setMounted] = useState(false); useEffect(() => { const selectorPrefixed = '#' + selector.replace(/^#/, ''); ref.current = document.querySelector(selectorPrefixed); if (!ref.current) { const div = document.createElement('div'); div.setAttribute('id', selector); document.body.appendChild(div); ref.current = div; } setMounted(true); }, [selector]); if (!ref.current) return null; return mounted ? createPortal(children, ref.current) : null; }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ const detectBrowser = () => { var _a; const browser = detect(); return (_a = browser === null || browser === void 0 ? void 0 : browser.name) !== null && _a !== void 0 ? _a : ''; }; const detectOS = () => { var _a; const browser = detect(); return (_a = browser === null || browser === void 0 ? void 0 : browser.os) !== null && _a !== void 0 ? _a : ''; }; const isIOS = () => { const os = detectOS(); return os.toLowerCase().includes('ios'); }; const isAndroid = () => { const os = detectOS(); return os.toLowerCase().includes('android'); }; const isMobile = () => { return isAndroid() || isIOS(); }; function flattenChildren(children) { const childrenArray = React.Children.toArray(children); return childrenArray.reduce((flatChildren, child) => { if (child.type === React.Fragment) { return flatChildren.concat(flattenChildren(child.props.children)); } flatChildren.push(child); return flatChildren; }, []); } const truncatedAddress = (address) => { const start = address.slice(0, 6); const end = address.slice(-6); return `${start} ... ${end}`; }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var styled = typeof styled$1.div === 'function' ? styled$1 : styled$1['default']; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var defaultTheme = { mobileWidth: 560 }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ const ErrorMessage = styled(motion.div) ` z-index: -1; pointer-events: auto; position: absolute; left: 50%; transform: translateX(-50%); width: var(--width); top: 64px; color: #fff; font-size: 14px; line-height: 20px; font-weight: 500; background: var(--ck-body-color-danger); border-radius: 20px; padding: 24px 46px 82px 24px; transition: width var(--duration) var(--ease); a { font-weight: 700; text-decoration: underline; } code { font-size: 0.9em; display: inline-block; font-family: monospace; margin: 1px; padding: 0 4px; border-radius: 8px; font-weight: bold; background: rgba(255, 255, 255, 0.1); } `; const FadeIn = keyframes ` from { opacity: 0; } to { opacity: 1; } `; const FadeInScaleUp = keyframes ` from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: scale(1); } `; const FadeInScaleDown = keyframes ` from { opacity: 0; transform: scale(1.1); } to { opacity: 1; transform: scale(1); } `; const FadeOut = keyframes ` from { opacity: 1; } to { opacity: 0; } `; const FadeOutScaleUp = keyframes ` from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(1.1); } `; const FadeOutScaleDown = keyframes ` from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.85); } `; const PageContent = styled(motion.div) ` max-width: 100%; width: 295px; padding-top: 48px; `; const TextWithHr = styled(motion.div) ` user-select: none; position: relative; display: block; text-align: center; color: var(--ck-body-color-muted); font-size: 15px; font-weight: 400; line-height: 21px; span { z-index: 2; position: relative; display: inline-block; user-select: none; pointer-events: none; padding: 0 14px; background: var(--ck-body-background); transition: background-color 200ms ease; } &:before { z-index: 2; content: ''; position: absolute; top: 50%; left: 0; right: 0; height: 1px; transform: translateY(-1px); background: var(--ck-body-divider); box-shadow: var(--ck-body-divider-box-shadow); } `; const ModalHeading = styled(motion.div) ` z-index: 3; pointer-events: none; user-select: none; position: absolute; top: 25px; left: 50%; display: flex; align-items: center; justify-content: center; height: 26px; transform: translateX(-50%); width: var(--width); text-align: center; font-size: 17px; line-height: 20px; font-weight: var(--ck-modal-heading-font-weight, 600); color: var(--ck-body-color); span { display: inline-block; } `; const ModalContentContainer = styled(motion.div) ` position: relative; padding: 0; `; const ModalContent = styled(motion.div) ` left: 0; right: 0; text-align: center; display: flex; flex-direction: column; gap: 12px; padding: 0 0 16px; @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { display: block; } `; const ModalH1 = styled(motion.h1) ` margin: 0; padding: 0; line-height: ${(props) => (props.$small ? 20 : 22)}px; font-size: ${(props) => (props.$small ? 17 : 19)}px; font-weight: var(--ck-modal-h1-font-weight, 600); color: ${(props) => { if (props.$error) return 'var(--ck-body-color-danger)'; if (props.$valid) return 'var(--ck-body-color-valid)'; return 'var(--ck-body-color)'; }}; > svg { position: relative; top: -2px; display: inline-block; vertical-align: middle; margin-right: 6px; } @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { margin-bottom: 6px; font-size: 17px; } `; const ModalBody = styled.div ` font-size: 16px; font-weight: 400; line-height: 21px; color: var(--ck-body-color-muted); strong { font-weight: 500; color: var(--ck-body-color); } `; const BackgroundOverlay = styled(motion.div) ` z-index: 1; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: var(--ck-overlay-background, rgba(71, 88, 107, 0.24)); backdrop-filter: var(--ck-overlay-backdrop-filter, none); opacity: 0; animation: ${(props) => (props.$active ? FadeIn : FadeOut)} 150ms ease-out both; `; const BoxIn = keyframes ` from{ opacity: 0; transform: scale(0.97); } to{ opacity: 1; transform: scale(1); } `; const BoxOut = keyframes ` from{ opacity: 1; transform: scale(1); } to{ opacity: 0; transform: scale(0.97); } `; const MobileBoxIn = keyframes ` from { transform: translate3d(0, 100%, 0); } to { transform: translate3d(0, 0%, 0); } `; const MobileBoxOut = keyframes ` from { opacity: 1; } to { opacity: 0; } `; const BoxContainer = styled(motion.div) ` z-index: 2; position: relative; color: var(--ck-body-color); animation: 150ms ease both; animation-name: ${BoxOut}; &.active { animation-name: ${BoxIn}; } &:before { content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: var(--width); height: var(--height); transform: translateX(-50%); backface-visibility: hidden; transition: all 200ms ease; border-radius: var(--ck-border-radius, 20px); background: var(--ck-body-background); box-shadow: var(--ck-modal-box-shadow); } @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { animation-name: ${MobileBoxOut}; animation-duration: 130ms; animation-timing-function: ease; &.active { animation-name: ${MobileBoxIn}; animation-duration: 300ms; animation-delay: 32ms; animation-timing-function: cubic-bezier(0.15, 1.15, 0.6, 1); } &:before { width: 100%; transition: 0ms height cubic-bezier(0.15, 1.15, 0.6, 1); will-change: height; } } `; const ControllerContainer = styled(motion.div) ` z-index: 3; position: absolute; top: 0; left: 50%; height: 64px; transform: translateX(-50%); backface-visibility: hidden; width: var(--width); transition: 0.2s ease width; pointer-events: auto; //border-bottom: 1px solid var(--ck-body-divider); `; const InnerContainer$1 = styled(motion.div) ` position: relative; overflow: hidden; height: var(--height); transition: 0.2s ease height; @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { transition: 0ms height cubic-bezier(0.15, 1.15, 0.6, 1); /* animation-delay: 34ms; */ } `; const PageContainer = styled(motion.div) ` z-index: 2; position: relative; top: 0; left: 50%; margin-left: calc(var(--width) / -2); width: var(--width); /* left: 0; */ /* width: 100%; */ display: flex; justify-content: center; align-items: center; transform-origin: center center; animation: 200ms ease both; &.active { animation-name: ${FadeInScaleDown}; } &.active-scale-up { animation-name: ${FadeInScaleUp}; } &.exit-scale-down { z-index: 1; pointer-events: none; position: absolute; /* top: 0; */ /* left: 0; */ animation-name: ${FadeOutScaleDown}; } &.exit { z-index: 1; pointer-events: none; position: absolute; /* top: 0; */ /* left: 0; */ /* left: 50%; */ /* transform: translateX(-50%); */ animation-name: ${FadeOutScaleUp}; animation-delay: 16.6667ms; } @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { /* animation: 0ms ease both; */ /* animation-delay: 35ms; */ animation: 0ms cubic-bezier(0.15, 1.15, 0.6, 1) both; &.active { animation-name: ${FadeIn}; } &.active-scale-up { animation-name: ${FadeIn}; } &.exit-scale-down { z-index: 3; animation-name: ${FadeOut}; } &.exit { z-index: 3; animation-name: ${FadeOut}; animation-delay: 0ms; } } `; const PageContents = styled(motion.div) ` margin: 0 auto; width: fit-content; padding: 29px 24px 24px; backface-visibility: hidden; `; const ModalContainer = styled.div ` z-index: 2147483646; // z-index set one below max (2147483647) for if we wish to layer things ontop of the modal in a seperate Portal position: fixed; inset: 0; `; const CloseButton = styled(motion.button) ` z-index: 3; cursor: pointer; position: absolute; top: 22px; right: 17px; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 16px; padding: 0; margin: 0; color: var(--ck-body-action-color); background: var(--ck-body-background); transition: background-color 200ms ease, transform 100ms ease; /* will-change: transform; */ svg { display: block; } &:hover { background: var(--ck-body-background-secondary); } &:active { transform: scale(0.9); } `; const BackButton = styled(motion.button) ` z-index: 3; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; border-radius: 16px; padding: 0; margin: 0; color: var(--ck-body-action-color); background: var(--ck-body-background); transition: background-color 200ms ease, transform 100ms ease; /* will-change: transform; */ svg { display: block; position: relative; left: -1px; } &:enabled { cursor: pointer; &:hover { background: var(--ck-body-background-secondary); } &:active { transform: scale(0.9); } } `; const InfoButton = styled(motion.button) ` z-index: 3; position: absolute; inset: 0; transform: translateX(-1px); display: flex; align-items: center; justify-content: center; border-radius: 16px; padding: 0; margin: 0; color: var(--ck-body-action-color); background: var(--ck-body-background); transition: background-color 200ms ease, transform 100ms ease; /* will-change: transform; */ svg { display: block; position: relative; } &:enabled { cursor: pointer; &:hover { background: var(--ck-body-background-secondary); } &:active { transform: scale(0.9); } } `; const Container$3 = styled(motion.div) ` --ease: cubic-bezier(0.25, 0.1, 0.25, 1); --duration: 200ms; --transition: height var(--duration) var(--ease), width var(--duration) var(--ease); z-index: 3; display: block; pointer-events: none; position: absolute; left: 50%; top: 50%; width: 100%; transform: translate3d(-50%, -50%, 0); backface-visibility: hidden; @media only screen and (max-width: ${defaultTheme.mobileWidth}px) { pointer-events: auto; left: 0; top: auto; bottom: -5px; transform: none; ${BoxContainer} { max-width: 448px; margin: 0 auto; &:before { width: 100%; border-radius: var(--ck-border-radius, 30px) var(--ck-border-radius, 30px) 0 0; } } ${PageContainer} { left: 0; right: 0; margin: 0 auto; width: auto; } ${PageContent} { margin: 0 auto; width: 100% !important; } ${ModalHeading} { top: 29px; } ${ModalContent} { gap: 12px; } ${ModalBody} { margin: 0 auto; max-width: 295px; } ${PageContents} { width: 100%; padding: 31px 24px; } ${ControllerContainer} { width: 100%; top: 4px; border-bottom: 0; } ${CloseButton} { right: 22px; } ${BackButton} { top: -1px; left: -3px; } ${InfoButton} { top: -1px; left: -3px; svg { width: 65%; height: auto; } } ${CloseButton}, ${BackButton}, ${InfoButton} { // Quick hack for bigger tappable area on mobile transform: scale(1.4) !important; background: transparent !important; svg { transform: scale(0.8) !important; } } } `; const KEYCODE_TAB = 9; function useFocusTrap() { const elRef = useRef(null); function handleFocus(e) { if (!elRef.current) return; const focusableEls = elRef.current.querySelectorAll(` a[href]:not(:disabled), button:not(:disabled), textarea:not(:disabled), input[type="text"]:not(:disabled), input[type="radio"]:not(:disabled), input[type="checkbox"]:not(:disabled), select:not(:disabled) `), firstFocusableEl = focusableEls[0], lastFocusableEl = focusableEls[focusableEls.length - 1]; const isTabPressed = e.key === 'Tab' || e.keyCode === KEYCODE_TAB; if (!isTabPressed) { return; } if (e.shiftKey) { /* shift + tab */ if (document.activeElement === firstFocusableEl) { lastFocusableEl.focus(); e.preventDefault(); } } /* tab */ else { if (document.activeElement === lastFocusableEl) { firstFocusableEl.focus(); e.preventDefault(); } } } useEffect(() => { if (elRef.current) { elRef.current.addEventListener('keydown', handleFocus); elRef.current.focus({ preventScroll: true }); } const current = elRef.current; return () => { if (current) { current.removeEventListener('keydown', handleFocus); } }; }, [elRef]); return elRef; } function FocusTrap(props) { const elRef = useFocusTrap(); useEffect(() => { if (!elRef.current) return; elRef.current.focus({ preventScroll: true }); }, [elRef]); return (jsx("div", { ref: elRef, tabIndex: 0, children: props.children })); } /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ function usePrevious(value, initial) { const ref = useRef({ target: value, previous: initial }); if (ref.current.target !== value) { // The value changed. ref.current.previous = ref.current.target; ref.current.target = value; } return ref.current.previous; } /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ const LOG_LEVEL = { debug: 10, info: 20, warn: 30, error: 40, none: 100 }; // Suppress `useLayoutEffect` warning when rendering on the server // https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85 const useIsoLayoutEffect = typeof window !== 'undefined' && window.document && window.document.createElement !== undefined ? useLayoutEffect : useEffect; const useFitText = ({ logLevel: logLevelOption = 'info', maxFontSize = 100, minFontSize = 20, onFinish, onStart, resolution = 5 } = {}) => { const logLevel = LOG_LEVEL[logLevelOption]; const initState = useCallback(() => { return { calcKey: 0, fontSize: maxFontSize, fontSizePrev: minFontSize, fontSizeMax: maxFontSize, fontSizeMin: minFontSize }; }, [maxFontSize, minFontSize]); const ref = useRef(null); const innerHtmlPrevRef = useRef(); const isCalculatingRef = useRef(false); const [state, setState] = useState(initState); const { calcKey, fontSize, fontSizeMax, fontSizeMin, fontSizePrev } = state; // Montior div size changes and recalculate on resize let animationFrameId = null; const [ro] = useState(() => new ResizeObserver(() => { animationFrameId = window.requestAnimationFrame(() => { if (isCalculatingRef.current) { return; } onStart && onStart(); isCalculatingRef.current = true; // `calcKey` is used in the dependencies array of // `useIsoLayoutEffect` below. It is incremented so that the font size // will be recalculated even if the previous state didn't change (e.g. // when the text fit initially). setState({ ...initState(), calcKey: calcKey + 1 }); }); })); useEffect(() => { if (ref.current) { ro.observe(ref.current); } return () => { animationFrameId && window.cancelAnimationFrame(animationFrameId); ro.disconnect(); }; }, [animationFrameId, ro]); // Recalculate when the div contents change const innerHtml = ref.current && ref.current.innerHTML; useEffect(() => { if (calcKey === 0 || isCalculatingRef.current) return; if (innerHtml !== innerHtmlPrevRef.current) { onStart && onStart(); setState({ ...initState(), calcKey: calcKey + 1 }); } innerHtmlPrevRef.current = innerHtml; }, [calcKey, initState, innerHtml, onStart]); // Check overflow and resize font useIsoLayoutEffect(() => { // Don't start calculating font size until the `resizeKey` is incremented // above in the `ResizeObserver` callback. This avoids an extra resize // on initialization. if (calcKey === 0) { return; } const isWithinResolution = Math.abs(fontSize - fontSizePrev) <= resolution; const isOverflow = !!ref.current && (ref.current.scrollHeight > ref.current.offsetHeight || ref.current.scrollWidth > ref.current.offsetWidth); const isFailed = isOverflow && fontSize === fontSizePrev; const isAsc = fontSize > fontSizePrev; // Return if the font size has been adjusted "enough" (change within `resolution`) // reduce font size by one increment if it's overflowing. if (isWithinResolution) { if (isFailed) { isCalculatingRef.current = false; if (logLevel <= LOG_LEVEL.info) { console.info(`[use-fit-text] reached \`minFontSize = ${minFontSize}\` without fitting text`); } } else if (isOverflow) { setState({ fontSize: isAsc ? fontSizePrev : fontSizeMin, fontSizeMax, fontSizeMin, fontSizePrev, calcKey }); } else { isCalculatingRef.current = false; onFinish && onFinish(fontSize); } return; } // Binary search to adjust font size let delta; let newMax = fontSizeMax; let newMin = fontSizeMin; if (isOverflow) { delta = isAsc ? fontSizePrev - fontSize : fontSizeMin - fontSize; newMax = Math.min(fontSizeMax, fontSize); } else { delta = isAsc ? fontSizeMax - fontSize : fontSizePrev - fontSize; newMin = Math.max(fontSizeMin, fontSize); } setState({ calcKey, fontSize: fontSize + delta / 2, fontSizeMax: newMax, fontSizeMin: newMin, fontSizePrev: fontSize }); }, [calcKey, fontSize, fontSizeMax, fontSizeMin, fontSizePrev, onFinish, ref, resolution]); return { fontSize, ref }; }; const FitText = React.forwardRef(({ children }, ref) => { const [ready, setReady] = React.useState(false); const { fontSize, ref: textRef } = useFitText({ logLevel: 'none', maxFontSize: 100, minFontSize: 70, onStart: () => setReady(true), onFinish: () => setReady(true) }); return (jsx("div", { ref: textRef, style: { visibility: ready ? 'visible' : 'hidden', // avoid flash of unstyled text fontSize: `${fontSize}%`, maxHeight: '100%', maxWidth: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' //lineHeight: `${21 * (fontSize / 100)}px`, //background: fontSize !== '100%' ? 'red' : undefined, // debug }, children: children })); }); FitText.displayName = 'FitText'; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var base = { light: { /** Connect Wallet Button */ '--ck-connectbutton-font-size': '15px', '--ck-connectbutton-color': '#373737', '--ck-connectbutton-background': '#F6F7F9', '--ck-connectbutton-background-secondary': '#FFFFFF', '--ck-connectbutton-hover-color': '#373737', '--ck-connectbutton-hover-background': '#F0F2F5', '--ck-connectbutton-active-color': '#373737', '--ck-connectbutton-active-background': '#EAECF1', '--ck-connectbutton-balance-color': '#373737', '--ck-connectbutton-balance-background': '#fff', '--ck-connectbutton-balance-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-background)', '--ck-connectbutton-balance-hover-background': '#F6F7F9', '--ck-connectbutton-balance-hover-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-hover-background)', '--ck-connectbutton-balance-active-background': '#F0F2F5', '--ck-connectbutton-balance-active-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-active-background)', /** Primary Button */ '--ck-primary-button-border-radius': '16px', '--ck-primary-button-color': '#373737', '--ck-primary-button-background': '#F6F7F9', //'--ck-primary-button-box-shadow': 'inset 0 0 0 1px #F0F0F0', '--ck-primary-button-font-weight': '600', '--ck-primary-button-hover-color': '#373737', '--ck-primary-button-hover-background': '#F0F2F5', //'--ck-primary-button-hover-box-shadow': 'inset 0 0 0 2px var(--ck-focus-color)', //'--ck-primary-button-active-background': '#EAECF1', /** Secondary Button */ '--ck-secondary-button-border-radius': '16px', '--ck-secondary-button-color': '#373737', '--ck-secondary-button-background': '#F6F7F9', //'--ck-secondary-button-box-shadow': '', //'--ck-secondary-button-font-weight': '', /** Tertiary Button */ '--ck-tertiary-button-background': '#FFFFFF', '--ck-secondary-button-hover-background': '#e0e4eb', /** Modal */ '--ck-modal-box-shadow': '0px 2px 4px rgba(0, 0, 0, 0.02)', '--ck-overlay-background': 'rgba(71, 88, 107, 0.24)', '--ck-body-color': '#373737', '--ck-body-color-muted': '#999999', '--ck-body-color-muted-hover': '#111111', '--ck-body-background': '#ffffff', '--ck-body-background-transparent': 'rgba(255,255,255,0)', '--ck-body-background-secondary': '#f6f7f9', '--ck-body-background-secondary-hover-background': '#e0e4eb', '--ck-body-background-secondary-hover-outline': '#4282FF', '--ck-body-background-tertiary': '#F3F4F7', '--ck-body-action-color': '#999999', '--ck-body-divider': '#f7f6f8', '--ck-body-color-danger': '#FF4E4E', '--ck-body-color-valid': '#32D74B', '--ck-siwe-border': '#F0F0F0', /** Disclaimer */ //'--ck-body-disclaimer-background': '#E3D6C9', //'--ck-body-disclaimer-box-shadow': 'none', '--ck-body-disclaimer-color': '#AAAAAB', '--ck-body-disclaimer-link-color': '#838485', '--ck-body-disclaimer-link-hover-color': '#000000', /** Tooltips */ '--ck-tooltip-background': '#ffffff', '--ck-tooltip-background-secondary': '#ffffff', '--ck-tooltip-color': '#999999', '--ck-tooltip-shadow': '0px 2px 10px rgba(0, 0, 0, 0.08)', /** Network dropdown */ '--ck-dropdown-button-color': '#999999', '--ck-dropdown-button-box-shadow': '0 0 0 1px rgba(0,0,0,0.01), 0px 0px 7px rgba(0, 0, 0, 0.05)', '--ck-dropdown-button-background': '#fff', '--ck-dropdown-button-hover-color': '#8B8B8B', '--ck-dropdown-button-hover-background': '#F5F7F9', /** QR Code */ '--ck-qr-dot-color': '#000000', '--ck-qr-border-color': '#f7f6f8', /** Misc. */ '--ck-focus-color': '#1A88F8', '--ck-spinner-color': 'var(--ck-focus-color)', '--ck-copytoclipboard-stroke': '#CCCCCC' }, dark: { '--ck-connectbutton-font-size': '15px', '--ck-connectbutton-color': '#ffffff', '--ck-connectbutton-background': '#383838', '--ck-connectbutton-background-secondary': '#282828', '--ck-connectbutton-hover-background': '#404040', '--ck-connectbutton-active-background': '#4D4D4D', '--ck-connectbutton-balance-color': '#fff', '--ck-connectbutton-balance-background': '#282828', '--ck-connectbutton-balance-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-background)', '--ck-connectbutton-balance-hover-background': '#383838', '--ck-connectbutton-balance-hover-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-hover-background)', '--ck-connectbutton-balance-active-background': '#404040', '--ck-connectbutton-balance-active-box-shadow': 'inset 0 0 0 1px var(--ck-connectbutton-active-background)', '--ck-primary-button-color': '#ffffff', '--ck-primary-button-background': '#383838', //'--ck-primary-button-box-shadow': 'inset 0 0 0 1px #3D3D3D', '--ck-primary-button-border-radius': '16px', '--ck-primary-button-font-weight': '600', '--ck-primary-button-hover-background': '#404040', //'--ck-primary-button-hover-box-shadow': 'inset 0 0 0 2px rgba(255, 255, 255, 0.4)', //'--ck-primary-button-active-background': '#4D4D4D', '--ck-primary-button-active-border-radius': '16px', '--ck-secondary-button-color': '#ffffff', '--ck-secondary-button-background': '#333333', '--ck-secondary-button-hover-background': '#4D4D4D', /** Tertiary Button */ '--ck-tertiary-button-background': '#424242', '--ck-focus-color': '#1A88F8', '--ck-overlay-background': 'rgba(0,0,0,0.4)', '--ck-body-color': '#ffffff', '--ck-body-color-muted': 'rgba(255, 255, 255, 0.4)', '--ck-body-color-muted-hover': 'rgba(255, 255, 255, 0.8)', '--ck-body-background': '#2B2B2B', '--ck-body-background-transparent': 'rgba(0,0,0,0)', '--ck-body-background-secondary': '#333333', '--ck-body-background-secondary-hover-background': '#4D4D4D', '--ck-body-background-secondary-hover-outline': '#ffffff', '--ck-body-background-tertiary': '#333333', '--ck-body-action-color': '#808080', '--ck-body-divider': '#383838', '--ck-body-color-danger': '#FF4E4E', '--ck-body-disclaimer-color': '#858585', '--ck-body-disclaimer-link-color': '#ADADAD', '--ck-body-disclaimer-link-hover-color': '#FFFFFF', '--ck-modal-box-shadow': '0px 2px 4px rgba(0, 0, 0, 0.02)', '--ck-copytoclipboard-stroke': '#555555', '--ck-tooltip-background': '#2B2B2B', '--ck-tooltip-background-secondary': '#333333', '--ck-tooltip-color': '#999999', '--ck-tooltip-shadow': '0px 2px 10px rgba(0, 0, 0, 0.08)', /** Network dropdown */ '--ck-dropdown-button-color': '#6C7381', '--ck-spinner-color': 'var(--ck-focus-color)', '--ck-qr-dot-color': '#ffffff', '--ck-qr-border-color': '#3d3d3d' } }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var web95 = { '--ck-font-family': 'Lato', '--ck-border-radius': '0px', '--ck-connectbutton-color': '#373737', '--ck-connectbutton-background': 'linear-gradient(180deg, #F0F0EA 0%, #FFFFFF 50%, #F0F0EA 100%) 100% 100% / 200% 200%, #F5F5F1', '--ck-connectbutton-box-shadow': ' 0 0 0 1px #003C74, 2px 2px 0px rgba(255, 255, 255, 0.75), -2px -2px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-connectbutton-border-radius': '4.5px', '--ck-connectbutton-hover-color': '#373737', '--ck-connectbutton-hover-background': 'linear-gradient(180deg, #F0F0EA 0%, #FFFFFF 50%, #F0F0EA 100%) 100% 0% / 200% 200%, #F5F5F1', '--ck-connectbutton-active-background': 'linear-gradient(180deg, #F0F0EA 0%, #FFFFFF 50%, #F0F0EA 100%) 100% 100% / 200% 200%, #F5F5F1', '--ck-connectbutton-balance-color': '#373737', '--ck-connectbutton-balance-background': '#fff', '--ck-connectbutton-balance-box-shadow': '0 0 0 1px #E4E7E7', '--ck-connectbutton-balance-hover-box-shadow': '0 0 0 1px #d7dbdb', '--ck-connectbutton-balance-active-box-shadow': '0 0 0 1px #bbc0c0', '--ck-focus-color': '#1A88F8', '--ck-overlay-background': 'rgba(0, 127, 128, 0.8)', '--ck-body-color': '#373737', '--ck-body-color-muted': '#808080', '--ck-body-color-muted-hover': '#111111', '--ck-body-background': '#F0EDE2', '--ck-body-background-transparent': 'rgba(255,255,255,0)', '--ck-body-background-secondary-hover-background': '#FAFAFA', '--ck-body-background-secondary-hover-outline': '#4282FF', '--ck-body-action-color': '#373737', '--ck-body-color-danger': '#FC6464', '--ck-body-color-valid': '#32D74B', '--ck-body-divider': '#919B9C', '--ck-body-divider-box-shadow': '0px 1px 0px #FBFBF8', // Primary button '--ck-primary-button-background': 'linear-gradient(180deg, #FFFFFF 0%, #F0F0EA 100%), #F5F5F1', '--ck-primary-button-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-primary-button-border-radius': '6px', // Primary button hover '--ck-primary-button-hover-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 5px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-primary-button-hover-border-radius': '6px', // Modal '--ck-modal-heading-font-weight': 400, '--ck-modal-box-shadow': ` inset 0px -3px 0px #0F37A9, inset -2px 0px 0px #0F37A9, inset 0px -4px 0px #0D5DDF, inset -4px 0px 0px #0D5DDF, inset 2px 0px 0px #0453DD, inset 0px 2px 0px #044FD1, inset 4px 0px 0px #4283EB, inset 0px 4px 0px #4283EB `, '--ck-modal-h1-font-weight': 400, // Secondary button '--ck-secondary-button-color': '#373737', '--ck-secondary-button-border-radius': '6px', '--ck-secondary-button-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-secondary-button-background': 'linear-gradient(180deg, #FFFFFF 0%, #F0F0EA 100%), #F5F5F1', // Secondary button hover '--ck-secondary-button-hover-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 4px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-body-background-secondary': 'rgba(0, 0, 0, 0.1)', '--ck-body-background-tertiary': 'linear-gradient(180deg, #FBFBFB 0%, #EFEFEE 100%)', '--ck-tertiary-border-radius': '0px', '--ck-tertiary-box-shadow': 'inset 0 0 0 1px #919B9C, 1px 1px 2px rgba(0, 0, 0, 0.15), inset -2px -2px 0px #FFFFFF', '--ck-body-button-text-align': 'left', '--ck-body-button-box-shadow': '0 2px 4px rgba(0, 0, 0, 0.05 )', '--ck-body-disclaimer-background': 'linear-gradient(180deg, #FBFBFB 0%, #EFEFEE 100%)', '--ck-body-disclaimer-box-shadow': ` inset 0px -3px 0px #0F37A9, inset -2px 0px 0px #0F37A9, inset 0px -4px 0px #0D5DDF, inset -4px 0px 0px #0D5DDF, inset 2px 0px 0px #0453DD, inset 4px 0px 0px #4283EB, inset 0 1px 0 0 #919B9C`, '--ck-body-disclaimer-font-size': '14px', '--ck-body-disclaimer-color': '#959594', '--ck-body-disclaimer-link-color': '#626262', '--ck-body-disclaimer-link-hover-color': '#000000', '--ck-qr-dot-color': '#000000', '--ck-qr-border-color': '#919B9C', '--ck-qr-border-radius': '0', '--ck-qr-background': '#FFFFFF', '--ck-copytoclipboard-stroke': 'rgba(55, 55, 55, 0.4)', '--ck-tooltip-background': 'linear-gradient(270deg, #F7F3E6 7.69%, #F5F7DA 100%)', '--ck-tooltip-background-secondary': '#f6f7f9', '--ck-tooltip-color': '#000000', '--ck-tooltip-shadow': ' 0 0 0 1.5px #2b2622, 0px 2px 10px rgba(0, 0, 0, 0.08)', '--ck-spinner-color': 'var(--ck-focus-color)', '--ck-dropdown-button-color': '#999999', '--ck-dropdown-button-box-shadow': '0 0 0 1px #A0A0A0, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-dropdown-button-background': 'linear-gradient(180deg, #FFFFFF 0%, #F0F0EA 100%), #F5F5F1', '--ck-dropdown-button-hover-background': 'linear-gradient(0deg, #FFFFFF 0%, #F0F0EA 100%), #F5F5F1', '--ck-dropdown-pending-color': '#ACA899', '--ck-dropdown-active-color': '#FFFFFF', '--ck-dropdown-active-static-color': '#ACA899', '--ck-dropdown-active-background': '#3F69BF', '--ck-dropdown-active-border-radius': '0', '--ck-dropdown-active-inset': '-12px', '--ck-dropdown-color': '#ACA899', '--ck-dropdown-background': '#FFFFFF', '--ck-dropdown-box-shadow': 'inset 0 0 0 1px #ACA899, 2px 2px 7px rgba(0, 0, 0, 0.15)', '--ck-dropdown-border-radius': '0', '--ck-alert-color': '#ACA899', '--ck-alert-background': 'linear-gradient(180deg, #FBFBFB 0%, #EFEFEE 100%)', '--ck-alert-box-shadow': 'inset 0 0 0 1px #919B9C, 1px 1px 2px rgba(0, 0, 0, 0.15), inset -2px -2px 0px #FFFFFF', '--ck-alert-border-radius': '0', /** Graphics options for our themes, not to be exposed to devs */ '--ck-graphic-primary-color': '#333333', '--ck-graphic-primary-background': '#FFFFFF', /* '--ck-graphic-secondary-color': '#7D7D7D', '--ck-graphic-secondary-background': 'linear-gradient(180deg, #FFFFFF 0%, #F0F0EA 100%), #F5F5F1', '--ck-graphic-secondary-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-graphic-compass-color': '#7D7D7D', */ '--ck-graphic-compass-background': '#FFFFFF', /* '--ck-graphic-compass-box-shadow': 'inset 0 0 0 1px #003C74, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC, inset -1px -2px 2px rgba(0, 0, 0, 0.2)', '--ck-graphic-globe-background': '#ffffff', '--ck-graphic-globe-lines': '#808080', '--ck-graphic-globe-box-shadow': ' 0 0 0 1px #999A9E, 1px 1px 0px rgba(255, 255, 255, 0.75), -1px -1px 0px rgba(0, 0, 0, 0.05), inset 0px 0px 0px 0px #97B9EC', */ '--ck-siwe-border': '#919B9C' }; /* Copyright 2018 - 2022 The Alephium Authors This file is part of the alephium project. The library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the library. If not, see <http://www.gnu.org/licenses/>. */ var retro = { '--ck-font-family': '"SF Pro Rounded",ui-rounded,"Nunito",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol"', '--ck-border-radius': '8px', '--ck-connectbutton-font-size': '17px', '--ck-connectbutton-color': '#000000', '--ck-connectbutton-background': '#ffffff', '--ck-connectbutton-box-shadow': '-4px 4px 0px #000000, inset 0 0 0 2px #000000', '--ck-connectbutton-border-radius': '8px', '--ck-connectbutton-hover-background': '#F3EDE8', '--ck-connectbutton-active-box-shadow': '0 0 0 0 #000000, inset 0 0 0 2px #000000', '--ck-connectbutton-balance-color': '#000000', '--ck-connectbutton-balance-background': '#F3EDE8', '--ck-connectbutton-balance-box-shadow': '-4px 4px 0px #000000, inset 0 0 0 2px #000000', '--ck-connectbutton-balance-hover-background': '#eee5dd', '--ck-connectbutton-balance-connectbutton-box-shadow': '-4px 8px 0px -4px #000000, inset 0 0 0 2px #000000', '--ck-connectbutton-balance-connectbutton-border-radius': '0px 8px 8px 0', '--ck-primary-button-color': '#373737', '--ck-primary-button-background': '#ffffff', '--ck-primary-button-box-shadow': 'inset 0 0 0 2px #000000, -4px 4px 0 0 #000000', '--ck-primary-button-border-radius': '8px', '--ck-primary-button-hover-background': '#F3EDE8', '--ck-primary-button-hover-box-shadow': 'inset 0 0 0 2px #000000, -0px 0px 0 0 #000000', '--ck-secondary-button-border-radius': '8px', '