mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
Patch over newest
This commit is contained in:
@@ -1,27 +1,25 @@
|
||||
<h1 align="center">Lux Explore</h1>
|
||||
<h1 align="center">Blockscout frontend</h1>
|
||||
|
||||
<p align="center">
|
||||
<span>Frontend application for </span>
|
||||
<a href="https://github.com/luxfi/explore/blob/master/README.md">Lux Explorer</a>
|
||||
<a href="https://github.com/blockscout/blockscout/blob/master/README.md">Blockscout</a>
|
||||
<span> blockchain explorer</span>
|
||||
</p>
|
||||
|
||||
## Running and configuring the app
|
||||
|
||||
App is distributed as a docker image. Here you can find information about the [package](https://github.com/luxfi/explore/pkgs/container/frontend) and its recent [releases](https://github.com/luxfi/explore/releases).
|
||||
App is distributed as a docker image. Here you can find information about the [package](https://github.com/blockscout/frontend/pkgs/container/frontend) and its recent [releases](https://github.com/blockscout/frontend/releases).
|
||||
|
||||
You can configure your app by passing necessary environment variables when starting the container. See full list of ENVs and their description [here](./docs/ENVS.md).
|
||||
|
||||
```sh
|
||||
docker run -p 3000:3000 --env-file <path-to-your-env-file> ghcr.io/luxfi/explore:latest
|
||||
docker run -p 3000:3000 --env-file <path-to-your-env-file> ghcr.io/blockscout/frontend:latest
|
||||
```
|
||||
|
||||
Alternatively, you can build your own docker image and run your app from that. Please follow this [guide](./docs/CUSTOM_BUILD.md).
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
For more information on migrating from the previous frontend, please see the [frontend migration docs](https://docs.blockscout.com/for-developers/frontend-migration).
|
||||
|
||||
>>>>>>> c463e20f1 (Update luxfi links)
|
||||
## Contributing
|
||||
|
||||
See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol. We expect contributors to follow our [code of conduct](./CODE_OF_CONDUCT.md) when submitting code or comments.
|
||||
@@ -30,6 +28,8 @@ See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol.
|
||||
- [App ENVs list](./docs/ENVS.md)
|
||||
- [Contribution guide](./docs/CONTRIBUTING.md)
|
||||
- [Making a custom build](./docs/CUSTOM_BUILD.md)
|
||||
- [Frontend migration guide](https://docs.blockscout.com/for-developers/frontend-migration)
|
||||
- [Manual deployment guide with backend and microservices](https://docs.blockscout.com/for-developers/deployment/manual-deployment-guide)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function useIssueUrl(backendVersion: string | undefined) {
|
||||
'frontend-version': [ config.UI.footer.frontendVersion, config.UI.footer.frontendCommit ].filter(Boolean).join('+'),
|
||||
'additional-information': `**User Agent:** ${ window.navigator.userAgent }`,
|
||||
});
|
||||
return `https://github.com/luxfi/explore/issues/new/?${ searchParams.toString() }`;
|
||||
return `https://github.com/blockscout/blockscout/issues/new/?${ searchParams.toString() }`;
|
||||
// we need to update link whenever page url changes
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ backendVersion, isLoading, router.asPath ]);
|
||||
|
||||
@@ -8,7 +8,7 @@ function generateCspPolicy() {
|
||||
descriptors.cloudFlare(),
|
||||
descriptors.gasHawk(),
|
||||
descriptors.googleAnalytics(),
|
||||
//descriptors.googleFonts(),
|
||||
descriptors.googleFonts(),
|
||||
descriptors.googleReCaptcha(),
|
||||
descriptors.growthBook(),
|
||||
descriptors.helia(),
|
||||
|
||||
Vendored
+5
-35
@@ -5,11 +5,6 @@
|
||||
|
||||
// prettier-ignore
|
||||
declare module "nextjs-routes" {
|
||||
import type {
|
||||
GetServerSidePropsContext as NextGetServerSidePropsContext,
|
||||
GetServerSidePropsResult as NextGetServerSidePropsResult
|
||||
} from "nextjs";
|
||||
|
||||
export type Route =
|
||||
| StaticRoute<"/404">
|
||||
| StaticRoute<"/account/api-key">
|
||||
@@ -105,33 +100,6 @@ declare module "nextjs-routes" {
|
||||
* route({ pathname: "/foos/[foo]", query: { foo: "bar" }}) will produce "/foos/bar".
|
||||
*/
|
||||
export declare function route(r: Route): string;
|
||||
|
||||
/**
|
||||
* Nearly identical to GetServerSidePropsContext from next, but further narrows
|
||||
* types based on nextjs-route's route data.
|
||||
*/
|
||||
export type GetServerSidePropsContext<
|
||||
Pathname extends Route["pathname"] = Route["pathname"],
|
||||
Preview extends NextGetServerSidePropsContext["previewData"] = NextGetServerSidePropsContext["previewData"]
|
||||
> = Omit<NextGetServerSidePropsContext, 'params' | 'query' | 'defaultLocale' | 'locale' | 'locales'> & {
|
||||
params: Extract<Route, { pathname: Pathname }>["query"];
|
||||
query: Query;
|
||||
defaultLocale?: undefined;
|
||||
locale?: Locale;
|
||||
locales?: undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Nearly identical to GetServerSideProps from next, but further narrows
|
||||
* types based on nextjs-route's route data.
|
||||
*/
|
||||
export type GetServerSideProps<
|
||||
Props extends { [key: string]: any } = { [key: string]: any },
|
||||
Pathname extends Route["pathname"] = Route["pathname"],
|
||||
Preview extends NextGetServerSideProps["previewData"] = NextGetServerSideProps["previewData"]
|
||||
> = (
|
||||
context: GetServerSidePropsContext<Pathname, Preview>
|
||||
) => Promise<NextGetServerSidePropsResult<Props>>
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
@@ -146,12 +114,13 @@ declare module "next/link" {
|
||||
} from "react";
|
||||
export * from "next/dist/client/link";
|
||||
|
||||
type Query = { query?: { [key: string]: string | string[] | undefined } };
|
||||
type StaticRoute = Exclude<Route, { query: any }>["pathname"];
|
||||
|
||||
export interface LinkProps
|
||||
extends Omit<NextLinkProps, "href" | "locale">,
|
||||
AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
href: Route | StaticRoute | Omit<Route, "pathname">
|
||||
href: Route | StaticRoute | Query;
|
||||
locale?: false;
|
||||
}
|
||||
|
||||
@@ -179,6 +148,7 @@ declare module "next/router" {
|
||||
|
||||
type NextTransitionOptions = NonNullable<Parameters<Router["push"]>[2]>;
|
||||
type StaticRoute = Exclude<Route, { query: any }>["pathname"];
|
||||
type Query = { query?: { [key: string]: string | string[] | undefined } };
|
||||
|
||||
interface TransitionOptions extends Omit<NextTransitionOptions, "locale"> {
|
||||
locale?: false;
|
||||
@@ -200,12 +170,12 @@ declare module "next/router" {
|
||||
locale?: Locale;
|
||||
locales?: undefined;
|
||||
push(
|
||||
url: Route | StaticRoute | Omit<Route, "pathname">,
|
||||
url: Route | StaticRoute | Query,
|
||||
as?: string,
|
||||
options?: TransitionOptions
|
||||
): Promise<boolean>;
|
||||
replace(
|
||||
url: Route | StaticRoute | Omit<Route, "pathname">,
|
||||
url: Route | StaticRoute | Query,
|
||||
as?: string,
|
||||
options?: TransitionOptions
|
||||
): Promise<boolean>;
|
||||
|
||||
+1
-4
@@ -2,7 +2,7 @@
|
||||
"name": "@luxfi/explore",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"homepage": "https://github.com/luxfi/explore#readme",
|
||||
"homepage": "https://github.com/blockscout/frontend#readme",
|
||||
"engines": {
|
||||
"node": "22.11.0",
|
||||
"npm": "10.9.0"
|
||||
@@ -45,8 +45,6 @@
|
||||
"@chakra-ui/anatomy": "^2.2.2",
|
||||
"@chakra-ui/lazy-utils": "2.0.5",
|
||||
"@chakra-ui/react": "2.7.1",
|
||||
"@chakra-ui/styled-system": "^2.9.2",
|
||||
"@chakra-ui/system": "^2.6.2",
|
||||
"@chakra-ui/theme-tools": "^2.0.18",
|
||||
"@cloudnouns/kit": "1.1.6",
|
||||
"@emotion/react": "^11.10.4",
|
||||
@@ -141,7 +139,6 @@
|
||||
"@types/dom-to-image": "^2.6.4",
|
||||
"@types/jest": "^29.2.0",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@types/lodash": "^4.17.7",
|
||||
"@types/mixpanel-browser": "^2.38.1",
|
||||
"@types/node": "20.16.7",
|
||||
"@types/phoenix": "^1.5.4",
|
||||
|
||||
+2
-6
@@ -10,9 +10,6 @@ import config from 'configs/app';
|
||||
import theme from 'theme/theme';
|
||||
import * as svgSprite from 'ui/shared/IconSvg';
|
||||
|
||||
|
||||
import { inter, drukWide } from 'theme/foundations/typography';
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx: DocumentContext) {
|
||||
const originalRenderPage = ctx.renderPage;
|
||||
@@ -33,12 +30,11 @@ class MyDocument extends Document {
|
||||
return initialProps;
|
||||
}
|
||||
|
||||
// className={inter.className}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
{ /* FONTS */ }
|
||||
<link
|
||||
href={ config.UI.fonts.heading?.url ?? 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap' }
|
||||
rel="stylesheet"
|
||||
@@ -60,7 +56,7 @@ class MyDocument extends Document {
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/assets/favicon/android-chrome-192x192.png"/>
|
||||
<link rel="preload" as="image" href={ svgSprite.href }/>
|
||||
</Head>
|
||||
<body className={`${inter.variable} ${drukWide.variable}`}>
|
||||
<body>
|
||||
<ColorModeScript initialColorMode={ theme.config.initialColorMode }/>
|
||||
<Main/>
|
||||
<NextScript/>
|
||||
|
||||
Generated
+5025
-3736
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
# Icons
|
||||
|
||||
This directory contains SVG icons that are used by the app.
|
||||
|
||||
Everything in this directory is generated by running `icons build`.
|
||||
|
||||
@@ -5,8 +5,6 @@ import {
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
|
||||
import luxColors from 'theme/foundations/lux-colors';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
@@ -17,7 +15,7 @@ const baseStyleList = defineStyle({
|
||||
[$bg.variable]: '#fff',
|
||||
[$shadow.variable]: 'shadows.2xl',
|
||||
_dark: {
|
||||
[$bg.variable]: luxColors.colors.muted, //'colors.gray.900',
|
||||
[$bg.variable]: 'colors.gray.900',
|
||||
[$shadow.variable]: 'shadows.dark-lg',
|
||||
},
|
||||
borderWidth: '0',
|
||||
@@ -38,7 +36,7 @@ const baseStyleItem = defineStyle({
|
||||
[$bg.variable]: 'colors.whiteAlpha.100',
|
||||
},
|
||||
},
|
||||
bg: luxColors.colors.level1,
|
||||
bg: $bg.reference,
|
||||
});
|
||||
|
||||
const baseStyle = definePartsStyle({
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import luxColors from './lux-colors';
|
||||
|
||||
const semanticTokens = {
|
||||
colors: {
|
||||
divider: {
|
||||
'default': luxColors.colors.muted4,
|
||||
_dark: luxColors.colors.muted4,
|
||||
'default': 'blackAlpha.200',
|
||||
_dark: 'whiteAlpha.200',
|
||||
},
|
||||
text: {
|
||||
'default': luxColors.colors.foreground,
|
||||
_dark: luxColors.colors.foreground,
|
||||
'default': 'blackAlpha.800',
|
||||
_dark: 'whiteAlpha.800',
|
||||
},
|
||||
text_secondary: {
|
||||
'default': luxColors.colors.muted,
|
||||
_dark: luxColors.colors.muted,
|
||||
'default': 'gray.500',
|
||||
_dark: 'gray.400',
|
||||
},
|
||||
link: {
|
||||
'default': luxColors.colors.muted2,
|
||||
_dark: luxColors.colors.muted2,
|
||||
'default': 'blue.600',
|
||||
_dark: 'blue.300',
|
||||
},
|
||||
link_hovered: {
|
||||
'default': luxColors.colors.foreground, //'blue.400',
|
||||
'default': 'blue.400',
|
||||
},
|
||||
icon_link_external: {
|
||||
'default': 'gray.300',
|
||||
|
||||
@@ -5,17 +5,23 @@ import config from 'configs/app';
|
||||
export const BODY_TYPEFACE = config.UI.fonts.body?.name ?? 'Inter';
|
||||
export const HEADING_TYPEFACE = config.UI.fonts.heading?.name ?? 'Poppins';
|
||||
|
||||
const drukWide = localFont({
|
||||
src: [
|
||||
{
|
||||
path: './fonts/Druk-Wide-Bold.ttf',
|
||||
weight: '700',
|
||||
style: 'normal'
|
||||
const typography = {
|
||||
fonts: {
|
||||
heading: `${ HEADING_TYPEFACE }, ${ theme.fonts.heading }`,
|
||||
body: `${ BODY_TYPEFACE }, ${ theme.fonts.body }`,
|
||||
},
|
||||
textStyles: {
|
||||
h2: {
|
||||
fontSize: [ '32px' ],
|
||||
fontWeight: '500',
|
||||
lineHeight: '40px',
|
||||
fontFamily: 'heading',
|
||||
},
|
||||
{
|
||||
path: './fonts/Druk-Wide-Medium.ttf',
|
||||
weight: '500',
|
||||
style: 'normal',
|
||||
h3: {
|
||||
fontSize: '24px',
|
||||
fontWeight: '500',
|
||||
lineHeight: '32px',
|
||||
fontFamily: 'heading',
|
||||
},
|
||||
h4: {
|
||||
fontSize: 'md',
|
||||
@@ -26,16 +32,4 @@ const drukWide = localFont({
|
||||
},
|
||||
};
|
||||
|
||||
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
|
||||
|
||||
|
||||
const fonts = {
|
||||
heading: `${drukWide.style.fontFamily}, ${ theme.fonts.heading }`,
|
||||
body: `${inter.style.fontFamily}, ${ theme.fonts.body }`,
|
||||
}
|
||||
|
||||
export {
|
||||
fonts as default,
|
||||
drukWide,
|
||||
inter
|
||||
}
|
||||
export default typography;
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ const global = (props: StyleFunctionProps) => ({
|
||||
body: {
|
||||
bg: mode('white', 'black')(props),
|
||||
...getDefaultTransitionProps(),
|
||||
WebkitTapHighlightColor: 'transparent',
|
||||
fontVariantLigatures: 'no-contextual',
|
||||
'-webkit-tap-highlight-color': 'transparent',
|
||||
'font-variant-ligatures': 'no-contextual',
|
||||
},
|
||||
mark: {
|
||||
bgColor: mode('green.100', 'green.800')(props),
|
||||
|
||||
+2
-2
@@ -7,12 +7,12 @@ import breakpoints from './foundations/breakpoints';
|
||||
import colors from './foundations/colors';
|
||||
import semanticTokens from './foundations/semanticTokens';
|
||||
import transition from './foundations/transition';
|
||||
import fonts from './foundations/typography';
|
||||
import typography from './foundations/typography';
|
||||
import zIndices from './foundations/zIndices';
|
||||
import global from './global';
|
||||
|
||||
const overrides = {
|
||||
fonts,
|
||||
...typography,
|
||||
...borders,
|
||||
colors,
|
||||
components,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import type { StyleFunctionProps } from '@chakra-ui/theme-tools';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
import luxColors from 'theme/foundations/lux-colors';
|
||||
|
||||
import getDefaultTransitionProps from './getDefaultTransitionProps';
|
||||
import getFormStyles from './getFormStyles';
|
||||
|
||||
@@ -35,7 +33,7 @@ export default function getOutlinedFieldStyles(props: StyleFunctionProps) {
|
||||
cursor: 'not-allowed',
|
||||
':-webkit-autofill': {
|
||||
// background color for disabled input which value was selected from browser autocomplete popup
|
||||
WebkitBoxShadow: `0 0 0px 1000px ${ mode('rgba(16, 17, 18, 0.08)', 'rgba(255, 255, 255, 0.08)')(props) } inset`,
|
||||
'-webkit-box-shadow': `0 0 0px 1000px ${ mode('rgba(16, 17, 18, 0.08)', 'rgba(255, 255, 255, 0.08)')(props) } inset`,
|
||||
},
|
||||
},
|
||||
_invalid: {
|
||||
@@ -49,7 +47,6 @@ export default function getOutlinedFieldStyles(props: StyleFunctionProps) {
|
||||
...formStyles.input.focus,
|
||||
zIndex: 1,
|
||||
boxShadow: 'md',
|
||||
color: luxColors.colors.muted2,
|
||||
},
|
||||
_placeholder: {
|
||||
color: formStyles.placeholder.default.color,
|
||||
|
||||
@@ -39,6 +39,10 @@ export interface AddressZilliqaParams {
|
||||
is_scilla_contract: boolean;
|
||||
}
|
||||
|
||||
export interface AddressZilliqaParams {
|
||||
is_scilla_contract: boolean;
|
||||
}
|
||||
|
||||
export interface AddressCounters {
|
||||
transactions_count: string;
|
||||
token_transfers_count: string;
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressImplementation } from 'types/api/addressParams';
|
||||
import type { SmartContractProxyType } from 'types/api/contract';
|
||||
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
@@ -19,10 +18,9 @@ import { formatAbi } from './utils';
|
||||
interface Props {
|
||||
implementations: Array<AddressImplementation>;
|
||||
isLoading?: boolean;
|
||||
proxyType?: SmartContractProxyType;
|
||||
}
|
||||
|
||||
const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading, proxyType }: Props) => {
|
||||
const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading }: Props) => {
|
||||
const router = useRouter();
|
||||
const sourceAddress = getQueryParamString(router.query.source_address);
|
||||
const tab = getQueryParamString(router.query.tab);
|
||||
@@ -50,7 +48,7 @@ const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading, pr
|
||||
selectedItem={ selectedItem }
|
||||
onItemSelect={ setSelectedItem }
|
||||
isLoading={ isInitialLoading }
|
||||
label={ proxyType === 'eip7702' ? 'Delegate address' : 'Implementation address' }
|
||||
label="Implementation address"
|
||||
mb={ 3 }
|
||||
/>
|
||||
<ContractMethodsFilters
|
||||
|
||||
+4
-11
@@ -239,18 +239,16 @@ const AddressPageContent = () => {
|
||||
addressQuery.data?.is_contract ? {
|
||||
id: 'contract',
|
||||
title: () => {
|
||||
const tabName = addressQuery.data.proxy_type === 'eip7702' ? 'Code' : 'Contract';
|
||||
|
||||
if (addressQuery.data.is_verified) {
|
||||
return (
|
||||
<>
|
||||
<span>{ tabName }</span>
|
||||
<span>Contract</span>
|
||||
<IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return tabName;
|
||||
return 'Contract';
|
||||
},
|
||||
component: (
|
||||
<AddressContract
|
||||
@@ -281,12 +279,7 @@ const AddressPageContent = () => {
|
||||
config.features.validators.isEnabled && addressQuery.data?.has_validated_blocks ?
|
||||
{ slug: 'validator', name: 'Validator', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } :
|
||||
undefined,
|
||||
addressQuery.data?.implementations?.length && addressQuery.data?.proxy_type !== 'eip7702' ?
|
||||
{ slug: 'proxy', name: 'Proxy', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } :
|
||||
undefined,
|
||||
addressQuery.data?.implementations?.length && addressQuery.data?.proxy_type === 'eip7702' ?
|
||||
{ slug: 'eip7702', name: 'EOA+code', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } :
|
||||
undefined,
|
||||
addressQuery.data?.implementations?.length ? { slug: 'proxy', name: 'Proxy', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } : undefined,
|
||||
addressQuery.data?.token ? { slug: 'token', name: 'Token', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } : undefined,
|
||||
isSafeAddress ? { slug: 'safe', name: 'Multisig: Safe', tagType: 'custom' as const, ordinal: -10 } : undefined,
|
||||
addressProfileAPIFeature.isEnabled && usernameApiTag ? {
|
||||
@@ -424,7 +417,7 @@ const AddressPageContent = () => {
|
||||
<>
|
||||
<TextAd mb={ 6 }/>
|
||||
<PageTitle
|
||||
title={ `${ addressQuery.data?.is_contract && addressQuery.data?.proxy_type !== 'eip7702' ? 'Contract' : 'Address' } details` }
|
||||
title={ `${ addressQuery.data?.is_contract ? 'Contract' : 'Address' } details` }
|
||||
backLink={ backLink }
|
||||
contentAfter={ titleContentAfter }
|
||||
secondRow={ titleSecondRow }
|
||||
|
||||
@@ -15,7 +15,7 @@ import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import type { FontFace } from 'use-font-face-observer';
|
||||
import useFontFaceObserver from 'use-font-face-observer';
|
||||
|
||||
import { drukWide, inter } from 'theme/foundations/typography';
|
||||
import { BODY_TYPEFACE, HEADING_TYPEFACE } from 'theme/foundations/typography';
|
||||
|
||||
const TAIL_LENGTH = 4;
|
||||
const HEAD_MIN_LENGTH = 4;
|
||||
@@ -33,8 +33,8 @@ const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled,
|
||||
const [ displayedString, setDisplayedString ] = React.useState(hash);
|
||||
|
||||
const isFontFaceLoaded = useFontFaceObserver([
|
||||
{ family: inter.style.fontFamily, weight: String(fontWeight) as FontFace['weight'] },
|
||||
{ family: drukWide.style.fontFamily, weight: String(fontWeight) as FontFace['weight'] },
|
||||
{ family: BODY_TYPEFACE, weight: String(fontWeight) as FontFace['weight'] },
|
||||
{ family: HEADING_TYPEFACE, weight: String(fontWeight) as FontFace['weight'] },
|
||||
]);
|
||||
|
||||
const calculateString = useCallback(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { debounce } from 'es-toolkit';
|
||||
import React from 'react';
|
||||
import useFontFaceObserver from 'use-font-face-observer';
|
||||
|
||||
import { inter } from 'theme/foundations/typography';
|
||||
import { BODY_TYPEFACE } from 'theme/foundations/typography';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
@@ -18,7 +18,7 @@ const TruncatedTextTooltip = ({ children, label, placement }: Props) => {
|
||||
const { isOpen, onToggle, onOpen, onClose } = useDisclosure();
|
||||
|
||||
const isFontFaceLoaded = useFontFaceObserver([
|
||||
{ family: inter.style.fontFamily },
|
||||
{ family: BODY_TYPEFACE },
|
||||
]);
|
||||
|
||||
const updatedTruncateState = React.useCallback(() => {
|
||||
|
||||
@@ -33,31 +33,31 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
|
||||
const drawSelection = React.useCallback((x0: number, x1: number) => {
|
||||
const diffX = x1 - x0;
|
||||
|
||||
d3.select(ref.current).attr('opacity', 1);
|
||||
d3.select(ref.current)
|
||||
.attr('opacity', 1);
|
||||
|
||||
d3.select(ref.current).select('.ChartSelectionX__line_left').attr('x1', x0).attr('x2', x0);
|
||||
d3.select(ref.current)
|
||||
.select('.ChartSelectionX__line_left')
|
||||
.attr('x1', x0)
|
||||
.attr('x2', x0);
|
||||
|
||||
d3.select(ref.current).select('.ChartSelectionX__line_right').attr('x1', x1).attr('x2', x1);
|
||||
d3.select(ref.current)
|
||||
.select('.ChartSelectionX__line_right')
|
||||
.attr('x1', x1)
|
||||
.attr('x2', x1);
|
||||
|
||||
d3.select(ref.current).select('.ChartSelectionX__rect').attr('x', diffX > 0 ? x0 : diffX + x0).attr('width', Math.abs(diffX));
|
||||
d3.select(ref.current)
|
||||
.select('.ChartSelectionX__rect')
|
||||
.attr('x', diffX > 0 ? x0 : diffX + x0)
|
||||
.attr('width', Math.abs(diffX));
|
||||
}, []);
|
||||
|
||||
const handleSelect = React.useCallback((x0: number, x1: number) => {
|
||||
const startDate = scale.invert(x0);
|
||||
const endDate = scale.invert(x1);
|
||||
|
||||
if (startDate && endDate && Math.abs(dayjs(startDate).diff(endDate, 'day')) > SELECTION_THRESHOLD) {
|
||||
const startDayjs = dayjs(startDate);
|
||||
const endDayjs = dayjs(endDate);
|
||||
|
||||
if (startDayjs.isValid() && endDayjs.isValid()) {
|
||||
const minDate = dayjs.min(startDayjs, endDayjs);
|
||||
const maxDate = dayjs.max(startDayjs, endDayjs);
|
||||
|
||||
if (minDate && maxDate) {
|
||||
onSelect([ minDate.toDate(), maxDate.toDate() ]);
|
||||
}
|
||||
}
|
||||
if (Math.abs(dayjs(startDate).diff(endDate, 'day')) > SELECTION_THRESHOLD) {
|
||||
onSelect([ dayjs.min(dayjs(startDate), dayjs(endDate)).toDate(), dayjs.max(dayjs(startDate), dayjs(endDate)).toDate() ]);
|
||||
}
|
||||
}, [ onSelect, scale ]);
|
||||
|
||||
@@ -66,14 +66,14 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
|
||||
startX.current = undefined;
|
||||
endX.current = undefined;
|
||||
d3.select(ref.current).attr('opacity', 0);
|
||||
}, []);
|
||||
}, [ ]);
|
||||
|
||||
const handelMouseUp = React.useCallback(() => {
|
||||
if (!isActive.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (startX.current !== undefined && endX.current !== undefined) {
|
||||
if (startX.current && endX.current) {
|
||||
handleSelect(startX.current, endX.current);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@ async function readEntriesPromise(directoryReader: FileSystemDirectoryReader): P
|
||||
reject,
|
||||
);
|
||||
});
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
export function convertFileEntryToFile(entry: FileSystemFileEntry, fullFilePath?: boolean): Promise<File> {
|
||||
|
||||
@@ -57,23 +57,17 @@ const getChakraStyles: (colorMode: ColorMode) => ChakraStylesConfig<Option> = (c
|
||||
py: 0,
|
||||
mx: 0,
|
||||
}),
|
||||
valueContainer: (provided, state) => {
|
||||
const size = state.selectProps.size as Size | undefined;
|
||||
return {
|
||||
...provided,
|
||||
...getValueContainerStyles(size),
|
||||
py: 0,
|
||||
};
|
||||
},
|
||||
singleValue: (provided, state) => {
|
||||
const size = state.selectProps.size as Size | undefined;
|
||||
return {
|
||||
...provided,
|
||||
mx: 0,
|
||||
transform: 'none',
|
||||
...getSingleValueStyles(size),
|
||||
};
|
||||
},
|
||||
valueContainer: (provided, state) => ({
|
||||
...provided,
|
||||
...getValueContainerStyles(state.selectProps.size),
|
||||
py: 0,
|
||||
}),
|
||||
singleValue: (provided, state) => ({
|
||||
...provided,
|
||||
mx: 0,
|
||||
transform: 'none',
|
||||
...getSingleValueStyles(state.selectProps.size),
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import getApiVersionUrl from './utils/getApiVersionUrl';
|
||||
|
||||
const MAX_LINKS_COLUMNS = 4;
|
||||
|
||||
const FRONT_VERSION_URL = `https://github.com/luxfi/explore/tree/${ config.UI.footer.frontendVersion }`;
|
||||
const FRONT_COMMIT_URL = `https://github.com/luxfi/explore/commit/${ config.UI.footer.frontendCommit }`;
|
||||
const FRONT_VERSION_URL = `https://github.com/blockscout/frontend/tree/${ config.UI.footer.frontendVersion }`;
|
||||
const FRONT_COMMIT_URL = `https://github.com/blockscout/frontend/commit/${ config.UI.footer.frontendCommit }`;
|
||||
|
||||
const Footer = () => {
|
||||
|
||||
@@ -47,25 +47,31 @@ const Footer = () => {
|
||||
icon: 'social/git' as const,
|
||||
iconSize: '18px',
|
||||
text: 'Contribute',
|
||||
url: 'https://github.com/luxfi',
|
||||
url: 'https://github.com/blockscout/blockscout',
|
||||
},
|
||||
{
|
||||
icon: 'social/twitter' as const,
|
||||
iconSize: '18px',
|
||||
text: 'X',
|
||||
url: 'https://x.com/luxdefi',
|
||||
text: 'X (ex-Twitter)',
|
||||
url: 'https://www.twitter.com/blockscoutcom',
|
||||
},
|
||||
{
|
||||
icon: 'social/discord' as const,
|
||||
iconSize: '24px',
|
||||
text: 'Discord',
|
||||
url: 'https://discord.gg/luxdefi',
|
||||
url: 'https://discord.gg/blockscout',
|
||||
},
|
||||
{
|
||||
icon: 'brands/blockscout' as const,
|
||||
iconSize: '18px',
|
||||
text: 'All chains',
|
||||
url: 'https://www.blockscout.com/chains-and-projects',
|
||||
},
|
||||
{
|
||||
icon: 'donate' as const,
|
||||
iconSize: '20px',
|
||||
text: 'Donate',
|
||||
url: 'https://github.com/sponsors/luxfi',
|
||||
url: 'https://github.com/sponsors/blockscout',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -122,7 +128,7 @@ const Footer = () => {
|
||||
</Link>
|
||||
</Flex>
|
||||
<Text mt={ 3 } fontSize="xs">
|
||||
Explore is a tool for inspecting and analyzing EVM based blockchains. Blockchain explorer for Lux Network.
|
||||
Explore is a tool for inspecting and analyzing EVM based blockchains. Blockchain explorer for Lux Networks.
|
||||
</Text>
|
||||
<Box mt={ 6 } alignItems="start" fontSize="xs" lineHeight={ 5 }>
|
||||
{ apiVersionUrl && (
|
||||
@@ -196,7 +202,7 @@ const Footer = () => {
|
||||
>
|
||||
{
|
||||
([
|
||||
{ title: 'Lux', links: BLOCKSCOUT_LINKS },
|
||||
{ title: 'Blockscout', links: BLOCKSCOUT_LINKS },
|
||||
...(linksData || []),
|
||||
])
|
||||
.slice(0, colNum)
|
||||
|
||||
@@ -6,8 +6,8 @@ export default function getApiVersionUrl(version: string | undefined): string |
|
||||
const [ tag, commit ] = version.split('.+commit.');
|
||||
|
||||
if (commit) {
|
||||
return `https://github.com/luxfi/explore/commit/${ commit }`;
|
||||
return `https://github.com/blockscout/blockscout/commit/${ commit }`;
|
||||
}
|
||||
|
||||
return `https://github.com/luxfi/explore/tree/${ tag }`;
|
||||
return `https://github.com/blockscout/blockscout/tree/${ tag }`;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import luxColors from 'theme/foundations/lux-colors';
|
||||
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
|
||||
|
||||
import useColors from './useColors';
|
||||
|
||||
type Props = {
|
||||
isExpanded?: boolean;
|
||||
isCollapsed?: boolean;
|
||||
@@ -8,15 +9,16 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function useNavLinkProps({ isExpanded, isCollapsed, isActive }: Props) {
|
||||
const colors = useColors();
|
||||
|
||||
return {
|
||||
itemProps: {
|
||||
py: '9px',
|
||||
display: 'flex',
|
||||
border: 'none',
|
||||
color: isActive ? luxColors.colors.foreground : luxColors.colors.muted2,
|
||||
bgColor: 'transparent',
|
||||
_hover: { color: luxColors.colors.accent },
|
||||
color: isActive ? colors.text.active : colors.text.default,
|
||||
bgColor: isActive ? colors.bg.active : colors.bg.default,
|
||||
_hover: { color: isActive ? colors.text.active : colors.text.hover },
|
||||
borderRadius: 'base',
|
||||
...getDefaultTransitionProps({ transitionProperty: 'width, padding' }),
|
||||
},
|
||||
textProps: {
|
||||
|
||||
@@ -5,7 +5,6 @@ import type { ChangeEvent, FormEvent, FocusEvent } from 'react';
|
||||
|
||||
import { useScrollDirection } from 'lib/contexts/scrollDirection';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import luxColors from 'theme/foundations/lux-colors';
|
||||
import ClearButton from 'ui/shared/ClearButton';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
@@ -164,9 +163,9 @@ const SearchBarInput = (
|
||||
paddingRight: '36px',
|
||||
},
|
||||
}}
|
||||
placeholder={ isMobile ? 'Search by address... ' : 'Search by address, txn hash, block, token... ' }
|
||||
placeholder={ isMobile ? 'Search by address / ... ' : 'Search by address / txn hash / block / token... ' }
|
||||
onChange={ handleChange }
|
||||
border={ '2px solid ' + luxColors.colors.muted3 }
|
||||
border={ isHomepage ? 'none' : '2px solid' }
|
||||
borderColor={ useColorModeValue('blackAlpha.100', 'whiteAlpha.200') }
|
||||
_focusWithin={{ _placeholder: { color: 'gray.300' } }}
|
||||
color={ useColorModeValue('black', 'white') }
|
||||
|
||||
Reference in New Issue
Block a user