Skip to content

Commit

Permalink
Merge 4e1de58 into e74153c
Browse files Browse the repository at this point in the history
  • Loading branch information
abtestingalpha authored Oct 9, 2024
2 parents e74153c + 4e1de58 commit 4be048d
Show file tree
Hide file tree
Showing 19 changed files with 1,551 additions and 0 deletions.
548 changes: 548 additions & 0 deletions packages/synapse-interface/components/Custom/CustomBridge.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { memo } from 'react'

import { getTimeMinutesFromNow } from '../utils/getTimeMinutesFromNow'

/**
* @param id unique identifier for progress bar instance
* @param startTime timestamp in seconds
* @param estDuration total duration in seconds
* @param isComplete completion status
*/

export const AnimatedProgressBar = memo(
({
id,
startTime,
estDuration,
isComplete,
}: {
id: string
startTime: number
estDuration: number
isComplete: boolean
}) => {
const currentTime = getTimeMinutesFromNow(0)
const elapsedTime = currentTime - startTime
const remainingTime = estDuration - elapsedTime
const percentElapsed = (elapsedTime / estDuration) * 100

const duration = isComplete ? 0.5 : remainingTime

const synapsePurple = 'hsl(265deg 100% 75%)'
const tailwindGreen400 = 'rgb(74 222 128)'
const height = 3

const progressId = `progress-${id}`
const maskId = `mask-${id}`

return (
<svg
id="animated-progress-bar"
key={Date.now()}
width="100%"
height={height}
xmlns="http://www.w3.org/2000/svg"
className="rounded-sm"
>
<defs>
<linearGradient id={progressId} spreadMethod="reflect" x1="0" x2="1">
<stop stopColor={synapsePurple} />
<stop stopColor={synapsePurple} offset=".25" />
<stop stopColor={synapsePurple} stopOpacity=".67" offset=".75" />
<stop stopColor={synapsePurple} stopOpacity=".67" offset="1" />
<animate
attributeName="x1"
values="0%; -6%"
dur=".67s"
repeatCount="indefinite"
/>
<animate
attributeName="x2"
values="3%; -3%"
dur=".67s"
repeatCount="indefinite"
/>
</linearGradient>
<clipPath id={maskId}>
<rect height="100%">
<animate
attributeName="width"
values={`${percentElapsed}%; 100%`}
dur={duration}
fill="freeze"
calcMode={isComplete && 'spline'}
keySplines=".8 0 .2 1"
/>
</rect>
</clipPath>
</defs>
<rect
width="100%"
height={height}
fill={`url(#${progressId})`}
clipPath={`url(#${maskId})`}
>
{isComplete && (
<animate
attributeName="fill"
values={`${synapsePurple}; hsl(185deg 100% 40%); ${tailwindGreen400}`}
keyTimes="0; .5; 1"
dur={duration}
fill="freeze"
/>
)}
</rect>
{isComplete && (
<animate
attributeName="fill"
values={`${tailwindGreen400}`}
dur="0.1s"
fill="freeze"
/>
)}
</svg>
)
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { type Chain } from '@/utils/types'

export const ChainOption = ({
option,
isSelected,
onSelect,
isOrigin,
}: {
option: any
isSelected: boolean
onSelect: (option: Chain) => void
isOrigin?: boolean
}) => {
return (
<li
key={option.id}
className={`
pl-2.5 pr-2.5 py-2.5 rounded-[.1875rem] border border-solid
hover:border-[--synapse-focus] active:opacity-40
cursor-pointer whitespace-nowrap group flex justify-between items-center
${
isSelected
? 'border-[--synapse-focus] hover:opacity-70'
: 'border-transparent'
}
`}
onClick={() => onSelect(option)}
>
<div className="flex items-center">
{option?.imgUrl && (
<img
src={option?.imgUrl}
alt={`${option?.name} chain icon`}
className="inline w-4 h-4 mr-2"
/>
)}
{option?.name}
</div>
</li>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import _ from 'lodash'
import { type Chain } from '@/utils/types'

import usePopover from '../hooks/usePopoverRef'
import { DownArrow } from '@/components/icons/DownArrow'
import { ChainOption } from './ChainOption'

type PopoverSelectProps = {
options: Chain[]
onSelect: (selected: Chain) => void
selected: Chain
label: string
isOrigin: boolean
}

export const ChainPopoverSelect = ({
options,
onSelect,
selected,
label,
isOrigin,
}: PopoverSelectProps) => {
const { popoverRef, isOpen, togglePopover, closePopover } = usePopover()

const handleSelect = (option: Chain) => {
onSelect(option)
closePopover()
}

return (
<div
data-test-id="chain-popover-select"
className="relative w-min col-span-full"
ref={popoverRef}
>
<div
id={`${isOrigin ? 'origin' : 'destination'}-chain-select`}
onClick={() => togglePopover()}
className={`
flex px-2.5 py-1.5 gap-2 items-center rounded
text-[--synapse-select-text] whitespace-nowrap
border border-solid border-zinc-200 dark:border-zinc-700
cursor-pointer hover:border-[--synapse-focus]
w-[150px]
`}
>
{selected?.chainImg && (
<img
src={selected?.chainImg.src}
alt={`${selected?.name} chain icon`}
className="inline w-4 h-4"
/>
)}
{selected?.name || 'Network'}
<DownArrow />
</div>
{isOpen && (
<div
className={`
bg-zinc-100 dark:bg-bgBase
absolute z-50 mt-1 max-h-60 min-w-48 rounded
shadow popover text-left list-none overflow-y-auto
border border-solid border-zinc-200 dark:border-zinc-700
animate-slide-down origin-top
`}
>
<ul className="p-0 m-0">
{options.map((option, i) => (
<ChainOption
key={i}
option={option}
isSelected={option?.name === selected?.name}
onSelect={() => handleSelect(option)}
isOrigin={isOrigin}
/>
))}
</ul>
</div>
)}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import _ from 'lodash'
import { type Chain } from '@/utils/types'

import { ChainPopoverSelect } from './ChainPopoverSelect'
import { ETH, OPTIMISM } from '@/constants/chains/master'

type Props = {
label: 'To' | 'From'
isOrigin: boolean
onChange: (newChain: Chain) => void
chain: Chain
}

export const ChainSelect = ({ label, isOrigin, chain, onChange }: Props) => {
const options = [OPTIMISM]

return (
<ChainPopoverSelect
options={options}
onSelect={(selected) => {
onChange(selected)
}}
selected={chain}
label={label}
isOrigin={isOrigin}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { debounce } from 'lodash'
import React, { useCallback } from 'react'
import { NumericFormat } from 'react-number-format'
import { joinClassNames } from '@/utils/joinClassNames'

interface CustomAmountInputTypes {
inputRef?: React.RefObject<HTMLInputElement>
disabled?: boolean
showValue: string
handleFromValueChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
setIsTyping?: (isTyping: boolean) => void
className?: string
}

export function CustomAmountInput({
inputRef,
disabled = false,
showValue,
handleFromValueChange,
setIsTyping,
className,
}: CustomAmountInputTypes) {
const debouncedSetIsTyping = useCallback(
debounce((value: boolean) => setIsTyping?.(value), 600),
[setIsTyping]
)

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setIsTyping?.(true)
debouncedSetIsTyping(false)
handleFromValueChange?.(event)
}

const inputClassNames = {
unset: 'bg-transparent border-none p-0',
layout: 'w-full',
placeholder: 'placeholder:text-zinc-500 placeholder:dark:text-zinc-400',
font: 'text-xl md:text-2xl font-medium',
focus: 'focus:outline-none focus:ring-0 focus:border-none',
custom: className,
}

return (
<NumericFormat
inputMode="numeric"
getInputRef={inputRef}
placeholder="0.0000"
value={showValue}
pattern={disabled ? '[0-9.]+' : '^[0-9]+([.,]?[0-9]+)?$'}
disabled={disabled}
readOnly={disabled}
onChange={handleInputChange}
className={joinClassNames(inputClassNames)}
name="inputRow"
minLength={1}
maxLength={79}
autoComplete="off"
thousandSeparator={true}
allowNegative={false}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useRef, useState } from 'react'

import { DownArrow } from '@/components/icons/DownArrow'
import useCloseOnOutsideClick from '@/utils/hooks/useCloseOnOutsideClick'
import { useCloseOnEscape } from '@/utils/hooks/useCloseOnEscape'

export const DropdownMenu = ({ menuTitleElement, children }) => {
const [open, setOpen] = useState<boolean>(false)
const ref = useRef(null)

const handleClick = () => {
setOpen(!open)
}

const closeDropdown = () => setOpen(false)

useCloseOnOutsideClick(ref, closeDropdown)
useCloseOnEscape(closeDropdown)

return (
<div className="relative" ref={ref}>
<div
onClick={handleClick}
className={`
flex place-items-center justify-center
px-2 py-1 rounded space-x-2 cursor-pointer
`}
>
{menuTitleElement}
<DownArrow />
</div>

{open && (
<ul
className={`
absolute z-50 mt-1 p-0 bg-zinc-100 dark:bg-bgBase rounded shadow popover -right-1 list-none text-left text-sm
`}
>
{children}
</ul>
)}
</div>
)
}
Loading

0 comments on commit 4be048d

Please sign in to comment.