Skip to content

Commit

Permalink
Token api (#210)
Browse files Browse the repository at this point in the history
Co-authored-by: Chen Yu <[email protected]>
Co-authored-by: zhangyouxin <[email protected]>
  • Loading branch information
Keith-CY and zhangyouxin authored Feb 4, 2024
1 parent 1f45c1f commit c384a2b
Show file tree
Hide file tree
Showing 35 changed files with 1,727 additions and 89 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@ant-design/icons": "4.8.1",
"@ckb-lumos/base": "0.21.0-next.1",
"@nervosnetwork/ckb-sdk-utils": "0.109.0",
"@sentry/react": "7.94.1",
"@sentry/tracing": "7.94.1",
Expand Down
Binary file added src/assets/alert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/arrow_down_black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/arrow_up_circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/delete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/modal_close.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions src/components/CommonButton/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.container {
background-color: var(--primary-color);
cursor: pointer;
user-select: none;
font-size: 16px;
padding: 14px 40px;
color: white;
border: none;
border-radius: 4px;
}

.container:hover {
background-color: var(--primary-color);
}

.isDisabled {
opacity: 0.5;
cursor: not-allowed;
}

.loading .dot {
display: inline-block;
animation: loading 1.5s infinite;
}

.loading {
margin-left: 4px;
}

@keyframes loading {
0% {
opacity: 0;
}

40% {
opacity: 1;
}

80% {
opacity: 0;
}
}

.loading .dot:nth-child(1) {
animation-delay: 0s;
}

.loading .dot:nth-child(2) {
animation-delay: 0.5s;
}

.loading .dot:nth-child(3) {
animation-delay: 1s;
}
31 changes: 31 additions & 0 deletions src/components/CommonButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import classNames from 'classnames'
import styles from './index.module.scss'

type Props = {
name: string
onClick: () => void
disabled?: boolean
loading?: boolean
className?: string
}

export default (props: Props) => {
const { name, onClick, disabled, loading, className } = props
return (
<button
type="button"
className={classNames(styles.container, (disabled || loading) && styles.isDisabled, className)}
onKeyDown={disabled ? undefined : onClick}
onClick={disabled ? undefined : onClick}
>
{name}
{loading && (
<span className={styles.loading}>
<span className={styles.dot}>.</span>
<span className={styles.dot}>.</span>
<span className={styles.dot}>.</span>
</span>
)}
</button>
)
}
27 changes: 27 additions & 0 deletions src/components/CommonModal/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.overlay {
display: block;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100vh;
overflow: hidden;
background-color: rgb(0 0 0 / 40%);
}

.container {
position: absolute;
z-index: 3;
top: 150px;
left: 50%;
transform: translateX(-50%);
background-color: white;
border-radius: 4px;
max-width: 90%;
box-shadow: 0 0 8px 0 rgb(0 0 0 / 20%);

@media screen and (width <= 750px) {
max-width: calc(100vw - 32px);
}
}
40 changes: 40 additions & 0 deletions src/components/CommonModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useEffect } from 'react'
import classNames from 'classnames'
import OutsideClickHandler from 'react-outside-click-handler'
import styles from './index.module.scss'

type Props = {
isOpen: boolean
children: React.ReactNode
onClose: () => void
className?: string
}

export default (props: Props) => {
const { isOpen, children, onClose, className } = props

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
// close modal when press ESC
if (event.keyCode === 27) {
onClose()
}
}
window.addEventListener('keydown', handleKeyDown)
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [onClose])

if (!isOpen) {
return null
}
return (
<>
<div className={styles.overlay} />
<OutsideClickHandler onOutsideClick={onClose}>
<div className={classNames(styles.container, className)}>{children}</div>
</OutsideClickHandler>
</>
)
}
57 changes: 57 additions & 0 deletions src/components/CommonSelect/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.select {
position: relative;
font-size: 14px;
padding: 11px 8px;
margin: 0 0 1rem;
border-radius: 4px;
border: 1px solid #e5e5e5;
background: white;
cursor: pointer;
user-select: none;
}

.value {
max-width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
}

.options {
position: absolute;
left: 0;
top: 45px;
border-radius: 4px;
border: 1px solid #e5e5e5;
background: white;
width: 100%;
}

.option {
padding: 11px 8px;
cursor: pointer;
font-size: 14px;
color: #333;
display: flex;
justify-content: space-between;
align-items: center;

&:hover {
background: #f5f5f5;
}
}

.arrow {
width: 10px;
transition: 0.3s;

&[data-is-flipped='true'] {
transform: rotateX(180deg);
}
}

.selected {
background: #f5f5f5;
}
100 changes: 100 additions & 0 deletions src/components/CommonSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
import classNames from 'classnames'
import { useEffect, useState } from 'react'
import OutsideClickHandler from 'react-outside-click-handler'
import styles from './index.module.scss'
import Arrow from '../../assets/arrow_down_black.png'

type Option = Record<'label' | 'value', string>
type Props = {
options: Option[]
onChange: (value: string) => void
defaultValue?: string
placeholder?: string
className?: string
}

function CommonSelect({ options, onChange, defaultValue, placeholder, className }: Props) {
const defaultLabel = options.find(option => option.value === defaultValue)?.label
const [value, setValue] = useState(defaultLabel)
const [isExpanded, setIsExpanded] = useState(false)
const toggleExpand = () => {
setIsExpanded(!isExpanded)
}

const handleOptionClick = (option: Option) => {
onChange(option.value)
setValue(option.label)
toggleExpand()
}

const [currentIndex, setCurrentIndex] = useState(-1)

useEffect(() => {
if (!isExpanded) {
// keyboard selection is enabled only when the dropdown is expanded
return
}
const handleKeyDown = (event: KeyboardEvent) => {
const { keyCode } = event
event.preventDefault()

switch (keyCode) {
case 38:
// up
setCurrentIndex(currentIndex > 0 ? currentIndex - 1 : currentIndex)
break
case 40:
// down
setCurrentIndex(currentIndex < options.length - 1 ? currentIndex + 1 : currentIndex)
break
case 27:
// esc
setCurrentIndex(-1)
toggleExpand()
break
case 13:
// enter
if (currentIndex !== -1) {
handleOptionClick(options[currentIndex])
}
toggleExpand()
break
default:
break
}
}

window.addEventListener('keydown', handleKeyDown)
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentIndex, isExpanded, options, options.length])

return (
<OutsideClickHandler onOutsideClick={() => setIsExpanded(false)}>
<div className={classNames(styles.select, className)}>
<div onClick={toggleExpand} className={styles.value}>
{value ?? placeholder}
<img src={Arrow} alt="arrow" className={styles.arrow} data-is-flipped={isExpanded} />
</div>
{isExpanded && (
<div className={styles.options}>
{options.map((option, index) => (
<div
key={option.label}
className={classNames(styles.option, index === currentIndex && styles.selected)}
onClick={() => handleOptionClick(option)}
>
{option.label}
</div>
))}
</div>
)}
</div>
</OutsideClickHandler>
)
}

export default CommonSelect
14 changes: 14 additions & 0 deletions src/components/Footer/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.tokenFormBtn {
font-size: 18px;
color: #acacac;
height: 23px;
margin: 8px 0;
user-select: none;
cursor: pointer;
background: transparent;
border: none;

&:hover {
color: var(--primary-color);
}
}
Loading

0 comments on commit c384a2b

Please sign in to comment.