upgrade react-bootstrap
This commit is contained in:
parent
54d69489b9
commit
6407455def
|
@ -1,30 +1,30 @@
|
|||
import { Accordion } from 'react-bootstrap'
|
||||
import Accordion from 'react-bootstrap/Accordion'
|
||||
import AccordionContext from 'react-bootstrap/AccordionContext'
|
||||
import { useAccordionButton } from 'react-bootstrap/AccordionButton'
|
||||
import ArrowRight from '../svgs/arrow-right-s-fill.svg'
|
||||
import ArrowDown from '../svgs/arrow-down-s-fill.svg'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useContext } from 'react'
|
||||
|
||||
export default function AccordianItem ({ header, body, headerColor = 'var(--theme-grey)', show }) {
|
||||
const [open, setOpen] = useState(show)
|
||||
function ContextAwareToggle ({ children, headerColor = 'var(--theme-grey)', eventKey }) {
|
||||
const { activeEventKey } = useContext(AccordionContext)
|
||||
const decoratedOnClick = useAccordionButton(eventKey)
|
||||
|
||||
useEffect(() => {
|
||||
setOpen(show)
|
||||
}, [])
|
||||
const isCurrentEventKey = activeEventKey === eventKey
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
defaultActiveKey={show ? '0' : undefined}
|
||||
>
|
||||
<Accordion.Toggle
|
||||
as={props => <div {...props} />}
|
||||
eventKey='0'
|
||||
style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }}
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{open
|
||||
<div style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }} onClick={decoratedOnClick}>
|
||||
{isCurrentEventKey
|
||||
? <ArrowDown style={{ fill: headerColor }} height={20} width={20} />
|
||||
: <ArrowRight style={{ fill: headerColor }} height={20} width={20} />}
|
||||
<div style={{ color: headerColor }}>{header}</div>
|
||||
</Accordion.Toggle>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function AccordianItem ({ header, body, headerColor = 'var(--theme-grey)', show }) {
|
||||
return (
|
||||
<Accordion defaultActiveKey={show ? '0' : undefined}>
|
||||
<ContextAwareToggle eventKey='0'><div style={{ color: headerColor }}>{header}</div></ContextAwareToggle>
|
||||
<Accordion.Collapse eventKey='0' className='mt-2'>
|
||||
<div>{body}</div>
|
||||
</Accordion.Collapse>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { useFormikContext } from 'formik'
|
||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
|
||||
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
|
||||
import Tooltip from 'react-bootstrap/Tooltip'
|
||||
|
||||
export default function ActionTooltip ({ children, notForm, disable, overlayText, placement }) {
|
||||
// if we're in a form, we want to hide tooltip on submit
|
||||
|
@ -21,7 +22,9 @@ export default function ActionTooltip ({ children, notForm, disable, overlayText
|
|||
trigger={['hover', 'focus']}
|
||||
show={formik?.isSubmitting ? false : undefined}
|
||||
>
|
||||
<span>
|
||||
{children}
|
||||
</span>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import AccordianItem from './accordian-item'
|
||||
import { Input, InputUserSuggest } from './form'
|
||||
import { InputGroup } from 'react-bootstrap'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import { BOOST_MIN } from '../lib/constants'
|
||||
import Info from './info'
|
||||
|
||||
|
@ -21,7 +21,7 @@ export default function AdvPostForm ({ edit }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>{edit ? 'add boost' : 'boost'}
|
||||
<Info>
|
||||
<ol className='font-weight-bold'>
|
||||
<ol className='fw-bold'>
|
||||
<li>Boost ranks posts higher temporarily based on the amount</li>
|
||||
<li>The minimum boost is {BOOST_MIN} sats</li>
|
||||
<li>Each {BOOST_MIN} sats of boost is equivalent to one trusted upvote
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useRef, useState } from 'react'
|
||||
import AvatarEditor from 'react-avatar-editor'
|
||||
import { Button, Form as BootstrapForm } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import BootstrapForm from 'react-bootstrap/Form'
|
||||
import Upload from './upload'
|
||||
import EditImage from '../svgs/image-edit-fill.svg'
|
||||
import Moon from '../svgs/moon-fill.svg'
|
||||
|
@ -28,7 +29,7 @@ export default function Avatar ({ onSuccess }) {
|
|||
<BootstrapForm.Control
|
||||
type='range' onChange={e => setScale(parseFloat(e.target.value))}
|
||||
min={1} max={2} step='0.05'
|
||||
defaultValue={scale} custom
|
||||
defaultValue={scale}
|
||||
/>
|
||||
</BootstrapForm.Group>
|
||||
<Button onClick={() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMutation } from '@apollo/client'
|
||||
import { gql } from 'graphql-tag'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
|
||||
export default function BookmarkDropdownItem ({ item: { id, meBookmark } }) {
|
||||
const [bookmarkItem] = useMutation(
|
||||
|
|
|
@ -4,7 +4,7 @@ import { gql, useApolloClient, useMutation } from '@apollo/client'
|
|||
import Countdown from './countdown'
|
||||
import AdvPostForm, { AdvPostInitial } from './adv-post-form'
|
||||
import FeeButton, { EditFeeButton } from './fee-button'
|
||||
import { InputGroup } from 'react-bootstrap'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import { bountySchema } from '../lib/validate'
|
||||
import { SubSelectInitial } from './sub-select-form'
|
||||
import CancelButton from './cancel-button'
|
||||
|
@ -95,7 +95,7 @@ export function BountyForm ({
|
|||
topLevel
|
||||
label={
|
||||
<>
|
||||
{textLabel} <small className='text-muted ml-2'>optional</small>
|
||||
{textLabel} <small className='text-muted ms-2'>optional</small>
|
||||
</>
|
||||
}
|
||||
name='text'
|
||||
|
@ -103,7 +103,7 @@ export function BountyForm ({
|
|||
hint={
|
||||
editThreshold
|
||||
? (
|
||||
<div className='text-muted font-weight-bold'>
|
||||
<div className='text-muted fw-bold'>
|
||||
<Countdown date={editThreshold} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { useRouter } from 'next/router'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
|
||||
export default function CancelButton ({ onClick }) {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<Button className='mr-3 text-muted nav-link font-weight-bold' variant='link' onClick={onClick || (() => router.back())}>cancel</Button>
|
||||
<Button className='me-3 text-muted nav-link fw-bold' variant='link' onClick={onClick || (() => router.back())}>cancel</Button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Form, MarkdownInput, SubmitButton } from '../components/form'
|
|||
import { gql, useMutation } from '@apollo/client'
|
||||
import styles from './reply.module.css'
|
||||
import { EditFeeButton } from './fee-button'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Delete from './delete'
|
||||
import { commentSchema } from '../lib/validate'
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import Flag from '../svgs/flag-fill.svg'
|
|||
import { abbrNum } from '../lib/format'
|
||||
import Share from './share'
|
||||
import ItemInfo from './item-info'
|
||||
import { Badge } from 'react-bootstrap'
|
||||
import Badge from 'react-bootstrap/Badge'
|
||||
import { RootProvider, useRoot } from './root'
|
||||
import { useMe } from './me'
|
||||
|
||||
|
@ -43,7 +43,7 @@ function Parent ({ item, rootText }) {
|
|||
</Link>
|
||||
{root.subName &&
|
||||
<Link href={`/~${root.subName}`}>
|
||||
{' '}<Badge className={itemStyles.newComment} variant={null}>{root.subName}</Badge>
|
||||
{' '}<Badge className={itemStyles.newComment} bg={null}>{root.subName}</Badge>
|
||||
</Link>}
|
||||
</>
|
||||
)
|
||||
|
@ -143,7 +143,7 @@ export default function Comment ({
|
|||
pendingSats={pendingSats}
|
||||
commentsText='replies'
|
||||
className={`${itemStyles.other} ${styles.other}`}
|
||||
embellishUser={op && <span className='text-boost font-weight-bold ml-1'>OP</span>}
|
||||
embellishUser={op && <Badge bg='boost' className={`ms-1 ${styles.op} bg-opacity-75`}>OP</Badge>}
|
||||
extraInfo={
|
||||
<>
|
||||
{includeParent && <Parent item={item} rootText={rootText} />}
|
||||
|
@ -170,7 +170,7 @@ export default function Comment ({
|
|||
}}
|
||||
/>)}
|
||||
{topLevel && (
|
||||
<span className='d-flex ml-auto align-items-center'>
|
||||
<span className='d-flex ms-auto align-items-center'>
|
||||
<Share item={item} />
|
||||
</span>
|
||||
)}
|
||||
|
@ -203,7 +203,7 @@ export default function Comment ({
|
|||
{root.bounty && !bountyPaid && <PayBounty item={item} />}
|
||||
</Reply>}
|
||||
{children}
|
||||
<div className={`${styles.comments} ml-sm-1 ml-md-3`}>
|
||||
<div className={`${styles.comments} ms-sm-1 ms-md-3`}>
|
||||
{item.comments && !noComments
|
||||
? item.comments.map((item) => (
|
||||
<Comment depth={depth + 1} key={item.id} item={item} />
|
||||
|
@ -220,7 +220,7 @@ export default function Comment ({
|
|||
function DepthLimit ({ item }) {
|
||||
if (item.ncomments > 0) {
|
||||
return (
|
||||
<Link href={`/items/${item.id}`} className='d-block p-3 font-weight-bold text-muted w-100 text-center'>
|
||||
<Link href={`/items/${item.id}`} className='d-block p-3 fw-bold text-muted w-100 text-center'>
|
||||
view replies
|
||||
</Link>
|
||||
)
|
||||
|
@ -252,7 +252,7 @@ export function CommentSkeleton ({ skeletonChildren }) {
|
|||
<div className={styles.replyPadder}>
|
||||
<div className={`${itemStyles.other} ${styles.reply} clouds`} />
|
||||
</div>
|
||||
<div className={`${styles.comments} ml-sm-1 ml-md-3`}>
|
||||
<div className={`${styles.comments} ms-sm-1 ms-md-3`}>
|
||||
{skeletonChildren
|
||||
? <CommentSkeleton skeletonChildren={skeletonChildren - 1} />
|
||||
: null}
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.op {
|
||||
margin-top: -1px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.collapsed .hunk {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ import { gql, useApolloClient, useLazyQuery } from '@apollo/client'
|
|||
import { useState } from 'react'
|
||||
import Comment, { CommentSkeleton } from './comment'
|
||||
import styles from './header.module.css'
|
||||
import { Nav, Navbar } from 'react-bootstrap'
|
||||
import Nav from 'react-bootstrap/Nav'
|
||||
import Navbar from 'react-bootstrap/Navbar'
|
||||
import { COMMENTS_QUERY } from '../fragments/items'
|
||||
import { COMMENTS } from '../fragments/comments'
|
||||
import { abbrNum } from '../lib/format'
|
||||
|
@ -19,7 +20,7 @@ export function CommentsHeader ({ handleSort, pinned, bio, parentCreatedAt, comm
|
|||
}
|
||||
|
||||
return (
|
||||
<Navbar className='pt-1 pb-0'>
|
||||
<Navbar className='pt-1 pb-0 px-3'>
|
||||
<Nav
|
||||
className={styles.navbarNav}
|
||||
activeKey={sort}
|
||||
|
@ -27,7 +28,7 @@ export function CommentsHeader ({ handleSort, pinned, bio, parentCreatedAt, comm
|
|||
<Nav.Item className='text-muted'>
|
||||
{abbrNum(commentSats)} sats
|
||||
</Nav.Item>
|
||||
<div className='ml-auto d-flex'>
|
||||
<div className='ms-auto d-flex'>
|
||||
<Nav.Item>
|
||||
<Nav.Link
|
||||
eventKey='hot'
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { Badge, OverlayTrigger, Tooltip } from 'react-bootstrap'
|
||||
import Badge from 'react-bootstrap/Badge'
|
||||
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
|
||||
import Tooltip from 'react-bootstrap/Tooltip'
|
||||
import CowboyHatIcon from '../svgs/cowboy.svg'
|
||||
|
||||
export default function CowboyHat ({ user, badge, className = 'ml-1', height = 16, width = 16 }) {
|
||||
export default function CowboyHat ({ user, badge, className = 'ms-1', height = 16, width = 16 }) {
|
||||
if (user?.streak === null || user.hideCowboyHat) {
|
||||
return null
|
||||
}
|
||||
|
@ -11,11 +13,11 @@ export default function CowboyHat ({ user, badge, className = 'ml-1', height = 1
|
|||
<HatTooltip overlayText={streak ? `${streak} days` : 'new'}>
|
||||
{badge
|
||||
? (
|
||||
<Badge variant='grey-medium' className='ml-2 d-inline-flex align-items-center'>
|
||||
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
|
||||
<CowboyHatIcon className={className} height={height} width={width} />
|
||||
<span className='ml-1'>{streak || 'new'}</span>
|
||||
<span className='ms-1 text-dark'>{streak || 'new'}</span>
|
||||
</Badge>)
|
||||
: <CowboyHatIcon className={className} height={height} width={width} />}
|
||||
: <span><CowboyHatIcon className={className} height={height} width={width} /></span>}
|
||||
</HatTooltip>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useMutation } from '@apollo/client'
|
||||
import { gql } from 'graphql-tag'
|
||||
import { useState } from 'react'
|
||||
import { Alert, Button, Dropdown } from 'react-bootstrap'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import { useShowModal } from './modal'
|
||||
|
||||
export default function Delete ({ itemId, children, onDelete }) {
|
||||
|
@ -63,7 +65,7 @@ function DeleteConfirm ({ onConfirm }) {
|
|||
return (
|
||||
<>
|
||||
{error && <Alert variant='danger' onClose={() => setError(undefined)} dismissible>{error}</Alert>}
|
||||
<p className='font-weight-bolder'>Are you sure? This is a gone forever kind of delete.</p>
|
||||
<p className='fw-bolder'>Are you sure? This is a gone forever kind of delete.</p>
|
||||
<div className='d-flex justify-content-end'>
|
||||
<Button
|
||||
variant='danger' onClick={async () => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { ITEM_FIELDS } from '../fragments/items'
|
|||
import AccordianItem from './accordian-item'
|
||||
import Item from './item'
|
||||
import Delete from './delete'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { discussionSchema } from '../lib/validate'
|
||||
import { SubSelectInitial } from './sub-select-form'
|
||||
import CancelButton from './cancel-button'
|
||||
|
@ -91,11 +91,11 @@ export function DiscussionForm ({
|
|||
/>
|
||||
<MarkdownInput
|
||||
topLevel
|
||||
label={<>{textLabel} <small className='text-muted ml-2'>optional</small></>}
|
||||
label={<>{textLabel} <small className='text-muted ms-2'>optional</small></>}
|
||||
name='text'
|
||||
minRows={6}
|
||||
hint={editThreshold
|
||||
? <div className='text-muted font-weight-bold'><Countdown date={editThreshold} /></div>
|
||||
? <div className='text-muted fw-bold'><Countdown date={editThreshold} /></div>
|
||||
: null}
|
||||
/>
|
||||
<AdvPostForm edit={!!item} />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { gql, useMutation } from '@apollo/client'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import FundError from './fund-error'
|
||||
import { useShowModal } from './modal'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Table } from 'react-bootstrap'
|
||||
import Table from 'react-bootstrap/Table'
|
||||
import ActionTooltip from './action-tooltip'
|
||||
import Info from './info'
|
||||
import styles from './fee-button.module.css'
|
||||
|
@ -31,7 +31,7 @@ function Receipt ({ cost, repetition, hasImgLink, baseFee, parentId, boost }) {
|
|||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td className='font-weight-bold'>{cost} sats</td>
|
||||
<td className='fw-bold'>{cost} sats</td>
|
||||
<td align='right' className='font-weight-light'>total fee</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
@ -90,7 +90,7 @@ function EditReceipt ({ cost, paidSats, addImgLink, boost, parentId }) {
|
|||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td className='font-weight-bold'>{cost} sats</td>
|
||||
<td className='fw-bold'>{cost} sats</td>
|
||||
<td align='right' className='font-weight-light'>total fee</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { Container, OverlayTrigger, Popover } from 'react-bootstrap'
|
||||
import Container from 'react-bootstrap/Container'
|
||||
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
|
||||
import Popover from 'react-bootstrap/Popover'
|
||||
import { CopyInput } from './form'
|
||||
import styles from './footer.module.css'
|
||||
import Texas from '../svgs/texas.svg'
|
||||
|
@ -15,7 +17,7 @@ import useDarkMode from './dark-mode'
|
|||
|
||||
const RssPopover = (
|
||||
<Popover>
|
||||
<Popover.Content style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<Popover.Body style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<div className='d-flex justify-content-center'>
|
||||
<a href='/rss' className='nav-link p-0 d-inline-flex'>
|
||||
home
|
||||
|
@ -38,13 +40,13 @@ const RssPopover = (
|
|||
jobs
|
||||
</a>
|
||||
</div>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
const SocialsPopover = (
|
||||
<Popover>
|
||||
<Popover.Content style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<Popover.Body style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<a
|
||||
href='https://snort.social/p/npub1jfujw6llhq7wuvu5detycdsq5v5yqf56sgrdq8wlgrryx2a2p09svwm0gx' className='nav-link p-0 d-inline-flex'
|
||||
target='_blank' rel='noreferrer'
|
||||
|
@ -72,13 +74,13 @@ const SocialsPopover = (
|
|||
>
|
||||
pod
|
||||
</a>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
const ChatPopover = (
|
||||
<Popover>
|
||||
<Popover.Content style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<Popover.Body style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<a
|
||||
href='https://tribes.sphinx.chat/t/stackerzchat' className='nav-link p-0 d-inline-flex'
|
||||
target='_blank' rel='noreferrer'
|
||||
|
@ -99,13 +101,13 @@ const ChatPopover = (
|
|||
>
|
||||
simplex
|
||||
</a>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
const AnalyticsPopover = (
|
||||
<Popover>
|
||||
<Popover.Content style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<Popover.Body style={{ fontWeight: 500, fontSize: '.9rem' }}>
|
||||
<a
|
||||
href='https://plausible.io/stacker.news' className='nav-link p-0 d-inline-flex'
|
||||
target='_blank' rel='noreferrer'
|
||||
|
@ -116,7 +118,7 @@ const AnalyticsPopover = (
|
|||
<Link href='/stackers/day' className='nav-link p-0 d-inline-flex'>
|
||||
stackers
|
||||
</Link>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
|
@ -151,7 +153,7 @@ export default function Footer ({ links = true }) {
|
|||
<>
|
||||
<div className='mb-1'>
|
||||
<DarkModeIcon onClick={darkModeToggle} width={20} height={20} className='fill-grey theme' suppressHydrationWarning />
|
||||
<LnIcon onClick={toggleLightning} width={20} height={20} className='ml-2 fill-grey theme' suppressHydrationWarning />
|
||||
<LnIcon onClick={toggleLightning} width={20} height={20} className='ms-2 fill-grey theme' suppressHydrationWarning />
|
||||
</div>
|
||||
<div className='mb-0' style={{ fontWeight: 500 }}>
|
||||
<Rewards />
|
||||
|
@ -207,7 +209,7 @@ export default function Footer ({ links = true }) {
|
|||
<div
|
||||
className={`text-small mx-auto mb-2 ${styles.connect}`}
|
||||
>
|
||||
<span className='nav-item text-muted mr-2'>connect:</span>
|
||||
<span className='nav-item text-muted me-2'>connect:</span>
|
||||
<CopyInput
|
||||
size='sm'
|
||||
groupClassName='mb-0 w-100'
|
||||
|
@ -219,23 +221,23 @@ export default function Footer ({ links = true }) {
|
|||
href='https://amboss.space/node/03cc1d0932bb99b0697f5b5e5961b83ab7fd66f1efc4c9f5c7bad66c1bcbe78f02'
|
||||
target='_blank' rel='noreferrer'
|
||||
>
|
||||
<Amboss className='ml-2 theme' width={20} height={20} />
|
||||
<Amboss className='ms-2 theme' width={20} height={20} />
|
||||
</a>
|
||||
</div>}
|
||||
<small className='d-flex justify-content-center align-items-center text-muted flex-wrap'>
|
||||
<a className={`${styles.contrastLink} d-flex align-items-center`} href='https://github.com/stackernews/stacker.news' target='_blank' rel='noreferrer'>
|
||||
FOSS <Github width={20} height={20} className='mx-1' />
|
||||
</a>
|
||||
made in Austin<Texas className='ml-1' width={20} height={20} />
|
||||
<span className='ml-1'>by</span>
|
||||
made in Austin<Texas className='ms-1' width={20} height={20} />
|
||||
<span className='ms-1'>by</span>
|
||||
<span>
|
||||
<Link href='/k00b' className='ml-1'>
|
||||
<Link href='/k00b' className='ms-1'>
|
||||
@k00b
|
||||
</Link>
|
||||
<Link href='/kr' className='ml-1'>
|
||||
<Link href='/kr' className='ms-1'>
|
||||
@kr
|
||||
</Link>
|
||||
<Link href='/ekzyis' className='ml-1'>
|
||||
<Link href='/ekzyis' className='ms-1'>
|
||||
@ekzyis
|
||||
</Link>
|
||||
</span>
|
||||
|
|
|
@ -6,7 +6,10 @@ import { Formik, Form as FormikForm, useFormikContext, useField, FieldArray } fr
|
|||
import React, { createContext, useContext, useEffect, useRef, useState } from 'react'
|
||||
import copy from 'clipboard-copy'
|
||||
import Thumb from '../svgs/thumb-up-fill.svg'
|
||||
import { Col, Dropdown as BootstrapDropdown, Nav } from 'react-bootstrap'
|
||||
import Col from 'react-bootstrap/Col'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import Nav from 'react-bootstrap/Nav'
|
||||
import Row from 'react-bootstrap/Row'
|
||||
import Markdown from '../svgs/markdown-line.svg'
|
||||
import styles from './form.module.css'
|
||||
import Text from '../components/text'
|
||||
|
@ -53,6 +56,7 @@ export function CopyInput (props) {
|
|||
onClick={handleClick}
|
||||
append={
|
||||
<Button
|
||||
className={styles.appendButton}
|
||||
size={props.size}
|
||||
onClick={handleClick}
|
||||
>
|
||||
|
@ -109,7 +113,7 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH
|
|||
<Nav.Link eventKey='preview' disabled={!meta.value}>preview</Nav.Link>
|
||||
</Nav.Item>
|
||||
<a
|
||||
className='ml-auto text-muted d-flex align-items-center'
|
||||
className='ms-auto text-muted d-flex align-items-center'
|
||||
href='https://guides.github.com/features/mastering-markdown/' target='_blank' rel='noreferrer'
|
||||
>
|
||||
<Markdown width={18} height={18} />
|
||||
|
@ -206,7 +210,7 @@ const insertMarkdownItalicFormatting = insertMarkdownFormatting(
|
|||
|
||||
function FormGroup ({ className, label, children }) {
|
||||
return (
|
||||
<BootstrapForm.Group className={className}>
|
||||
<BootstrapForm.Group className={`form-group ${className}`}>
|
||||
{label && <BootstrapForm.Label>{label}</BootstrapForm.Label>}
|
||||
{children}
|
||||
</BootstrapForm.Group>
|
||||
|
@ -244,11 +248,7 @@ function InputInner ({
|
|||
return (
|
||||
<>
|
||||
<InputGroup hasValidation>
|
||||
{prepend && (
|
||||
<InputGroup.Prepend>
|
||||
{prepend}
|
||||
</InputGroup.Prepend>
|
||||
)}
|
||||
<BootstrapForm.Control
|
||||
onKeyDown={(e) => {
|
||||
const metaOrCtrl = e.metaKey || e.ctrlKey
|
||||
|
@ -274,8 +274,6 @@ function InputInner ({
|
|||
isInvalid={invalid}
|
||||
isValid={showValid && meta.initialValue !== meta.value && meta.touched && !meta.error}
|
||||
/>
|
||||
{(append || (clear && field.value)) && (
|
||||
<InputGroup.Append>
|
||||
{(clear && field.value) &&
|
||||
<Button
|
||||
variant={null}
|
||||
|
@ -288,12 +286,10 @@ function InputInner ({
|
|||
onChange(formik, { target: { value: '' } })
|
||||
}
|
||||
}}
|
||||
className={`${styles.clearButton} ${invalid ? styles.isInvalid : ''}`}
|
||||
className={`${styles.clearButton} ${styles.appendButton} ${invalid ? styles.isInvalid : ''}`}
|
||||
><CloseIcon className='fill-grey' height={20} width={20} />
|
||||
</Button>}
|
||||
{append}
|
||||
</InputGroup.Append>
|
||||
)}
|
||||
<BootstrapForm.Control.Feedback type='invalid'>
|
||||
{meta.touched && meta.error}
|
||||
</BootstrapForm.Control.Feedback>
|
||||
|
@ -357,10 +353,10 @@ export function InputUserSuggest ({ label, groupClassName, ...props }) {
|
|||
}
|
||||
}}
|
||||
/>
|
||||
<BootstrapDropdown show={suggestions.array.length > 0}>
|
||||
<BootstrapDropdown.Menu className={styles.suggestionsMenu}>
|
||||
<Dropdown show={suggestions.array.length > 0}>
|
||||
<Dropdown.Menu className={styles.suggestionsMenu}>
|
||||
{suggestions.array.map((v, i) =>
|
||||
<BootstrapDropdown.Item
|
||||
<Dropdown.Item
|
||||
key={v.name}
|
||||
active={suggestions.index === i}
|
||||
onClick={() => {
|
||||
|
@ -369,9 +365,9 @@ export function InputUserSuggest ({ label, groupClassName, ...props }) {
|
|||
}}
|
||||
>
|
||||
{v.name}
|
||||
</BootstrapDropdown.Item>)}
|
||||
</BootstrapDropdown.Menu>
|
||||
</BootstrapDropdown>
|
||||
</Dropdown.Item>)}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</FormGroup>
|
||||
)
|
||||
}
|
||||
|
@ -394,14 +390,14 @@ export function VariableInput ({ label, groupClassName, name, hint, max, min, re
|
|||
<>
|
||||
{options?.map((_, i) => (
|
||||
<div key={i}>
|
||||
<BootstrapForm.Row className='mb-2'>
|
||||
<Row className='mb-2'>
|
||||
<Col>
|
||||
<InputInner name={`${name}[${i}]`} {...props} readOnly={i < readOnlyLen} placeholder={i >= min ? 'optional' : undefined} />
|
||||
</Col>
|
||||
{options.length - 1 === i && options.length !== max
|
||||
? <AddIcon className='fill-grey align-self-center pointer mx-2' onClick={() => fieldArrayHelpers.push('')} />
|
||||
? <Col className='d-flex ps-0' xs='auto'><AddIcon className='fill-grey align-self-center justify-self-center pointer' onClick={() => fieldArrayHelpers.push('')} /></Col>
|
||||
: null}
|
||||
</BootstrapForm.Row>
|
||||
</Row>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
|
@ -423,10 +419,9 @@ export function Checkbox ({ children, label, groupClassName, hiddenLabel, extra,
|
|||
// return the correct bag of props for you
|
||||
const [field,, helpers] = useField({ ...props, type: 'checkbox' })
|
||||
return (
|
||||
<BootstrapForm.Group className={groupClassName}>
|
||||
<FormGroup className={groupClassName}>
|
||||
{hiddenLabel && <BootstrapForm.Label className='invisible'>{label}</BootstrapForm.Label>}
|
||||
<BootstrapForm.Check
|
||||
custom
|
||||
id={props.id || props.name}
|
||||
inline={inline}
|
||||
>
|
||||
|
@ -444,7 +439,7 @@ export function Checkbox ({ children, label, groupClassName, hiddenLabel, extra,
|
|||
</div>}
|
||||
</BootstrapForm.Check.Label>
|
||||
</BootstrapForm.Check>
|
||||
</BootstrapForm.Group>
|
||||
</FormGroup>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -497,8 +492,7 @@ export function Select ({ label, items, groupClassName, onChange, noForm, overri
|
|||
|
||||
return (
|
||||
<FormGroup label={label} className={groupClassName}>
|
||||
<BootstrapForm.Control
|
||||
as='select'
|
||||
<BootstrapForm.Select
|
||||
{...field} {...props}
|
||||
onChange={(e) => {
|
||||
if (field?.onChange) {
|
||||
|
@ -509,11 +503,10 @@ export function Select ({ label, items, groupClassName, onChange, noForm, overri
|
|||
onChange(formik, e)
|
||||
}
|
||||
}}
|
||||
custom
|
||||
isInvalid={invalid}
|
||||
>
|
||||
{items.map(item => <option key={item}>{item}</option>)}
|
||||
</BootstrapForm.Control>
|
||||
</BootstrapForm.Select>
|
||||
<BootstrapForm.Control.Feedback type='invalid'>
|
||||
{meta.touched && meta.error}
|
||||
</BootstrapForm.Control.Feedback>
|
||||
|
|
|
@ -19,15 +19,23 @@
|
|||
height: auto;
|
||||
}
|
||||
|
||||
.appendButton {
|
||||
border-left: 0 !important;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.clearButton {
|
||||
background-color: var(--theme-inputBg);
|
||||
border: 1px solid var(--theme-borderColor);
|
||||
padding: 0rem 0.5rem;
|
||||
border-left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.clearButton:hover, .clearButton:active {
|
||||
background-color: var(--theme-inputBg) !important;
|
||||
border: 1px solid var(--theme-borderColor) !important;
|
||||
border-left: 0 !important;
|
||||
}
|
||||
.clearButton.isInvalid {
|
||||
border-color: #c03221;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import Link from 'next/link'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
|
||||
export default function FundError ({ onClose }) {
|
||||
return (
|
||||
<>
|
||||
<p className='font-weight-bolder'>you need more sats</p>
|
||||
<p className='fw-bolder'>you need more sats</p>
|
||||
<div className='d-flex justify-content-end'>
|
||||
<Link href='/wallet?type=fund'>
|
||||
<Button variant='success' onClick={onClose}>fund</Button>
|
||||
|
|
|
@ -3,7 +3,9 @@ import Nav from 'react-bootstrap/Nav'
|
|||
import Link from 'next/link'
|
||||
import styles from './header.module.css'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Button, Container, NavDropdown } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Container from 'react-bootstrap/Container'
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown'
|
||||
import Price from './price'
|
||||
import { useMe } from './me'
|
||||
import Head from 'next/head'
|
||||
|
@ -37,7 +39,7 @@ function Back () {
|
|||
}, [router.asPath])
|
||||
|
||||
if (show) {
|
||||
return <a role='button' tabIndex='0' className='nav-link standalone p-0' onClick={() => router.back()}><BackArrow className='theme mr-1 mr-md-2' width={22} height={22} /></a>
|
||||
return <a role='button' tabIndex='0' className='nav-link standalone p-0' onClick={() => router.back()}><BackArrow className='theme me-1 me-md-2' width={22} height={22} /></a>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -54,8 +56,8 @@ function NotificationBell () {
|
|||
<link rel='shortcut icon' href={data?.hasNewNotes ? '/favicon-notify.png' : '/favicon.png'} />
|
||||
</Head>
|
||||
<Link href='/notifications' passHref legacyBehavior>
|
||||
<Nav.Link eventKey='notifications' className='pl-0 position-relative'>
|
||||
<NoteIcon height={22} width={22} className='theme' />
|
||||
<Nav.Link eventKey='notifications' className='ps-0 position-relative'>
|
||||
<NoteIcon height={22} width={22} className='theme' style={{ marginTop: '-4px' }} />
|
||||
{data?.hasNewNotes &&
|
||||
<span className={styles.notification}>
|
||||
<span className='invisible'>{' '}</span>
|
||||
|
@ -70,23 +72,23 @@ function StackerCorner ({ dropNavKey }) {
|
|||
const me = useMe()
|
||||
|
||||
return (
|
||||
<div className='d-flex align-items-center ml-auto'>
|
||||
<div className='d-flex ms-auto'>
|
||||
<NotificationBell />
|
||||
<div className='position-relative'>
|
||||
<NavDropdown
|
||||
className={styles.dropdown}
|
||||
title={
|
||||
<Nav.Link eventKey={me.name} as='span' className='p-0 d-flex align-items-center' onClick={e => e.preventDefault()}>
|
||||
<Nav.Link eventKey={me.name} as='span' className='p-0' onClick={e => e.preventDefault()}>
|
||||
{`@${me.name}`}<CowboyHat user={me} />
|
||||
</Nav.Link>
|
||||
}
|
||||
alignRight
|
||||
align='end'
|
||||
>
|
||||
<Link href={'/' + me.name} passHref legacyBehavior>
|
||||
<NavDropdown.Item active={me.name === dropNavKey}>
|
||||
profile
|
||||
{me && !me.bioId &&
|
||||
<div className='p-1 d-inline-block bg-secondary ml-1'>
|
||||
<div className='p-1 d-inline-block bg-secondary ms-1'>
|
||||
<span className='invisible'>{' '}</span>
|
||||
</div>}
|
||||
</NavDropdown.Item>
|
||||
|
@ -147,9 +149,9 @@ function LurkerCorner ({ path }) {
|
|||
}), [router])
|
||||
|
||||
return path !== '/login' && path !== '/signup' && !path.startsWith('/invites') &&
|
||||
<div className='ml-auto'>
|
||||
<div className='ms-auto'>
|
||||
<Button
|
||||
className='align-items-center px-3 py-1 mr-2'
|
||||
className='align-items-center px-3 py-1 me-2'
|
||||
id='signup'
|
||||
style={{ borderWidth: '2px' }}
|
||||
variant='outline-grey-darkmode'
|
||||
|
@ -158,7 +160,7 @@ function LurkerCorner ({ path }) {
|
|||
login
|
||||
</Button>
|
||||
<Button
|
||||
className='align-items-center pl-2 py-1 pr-3'
|
||||
className='align-items-center ps-2 py-1 pe-3'
|
||||
style={{ borderWidth: '2px' }}
|
||||
id='login'
|
||||
onClick={() => handleLogin('/signup')}
|
||||
|
@ -166,7 +168,7 @@ function LurkerCorner ({ path }) {
|
|||
<LightningIcon
|
||||
width={17}
|
||||
height={17}
|
||||
className='mr-1'
|
||||
className='me-1'
|
||||
/>sign up
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -232,7 +234,7 @@ export default function Header ({ sub }) {
|
|||
const me = useMe()
|
||||
|
||||
return (
|
||||
<Container as='header' className='px-0'>
|
||||
<Container as='header'>
|
||||
<Navbar className='pb-0 pb-lg-2'>
|
||||
<Nav
|
||||
className={styles.navbarNav}
|
||||
|
@ -249,11 +251,11 @@ export default function Header ({ sub }) {
|
|||
<NavItems className='d-none d-lg-flex mx-2' prefix={prefix} sub={sub} />
|
||||
<PostItem className='d-none d-lg-flex mx-2' prefix={prefix} />
|
||||
<Link href={prefix + '/search'} passHref legacyBehavior>
|
||||
<Nav.Link eventKey='search' className='position-relative d-none d-lg-flex align-items-center pr-0 ml-2'>
|
||||
<Nav.Link eventKey='search' className='position-relative d-none d-lg-flex align-items-center pe-0 ms-2'>
|
||||
<SearchIcon className='theme' width={22} height={22} />
|
||||
</Nav.Link>
|
||||
</Link>
|
||||
<Nav.Item className={`${styles.price} ml-auto align-items-center ${me?.name.length > 10 ? 'd-none d-lg-flex' : ''}`}>
|
||||
<Nav.Item className={`${styles.price} ms-auto align-items-center ${me?.name.length > 10 ? 'd-none d-lg-flex' : ''}`}>
|
||||
<Price className='nav-link text-monospace' />
|
||||
</Nav.Item>
|
||||
{me ? <StackerCorner dropNavKey={dropNavKey} /> : <LurkerCorner path={path} />}
|
||||
|
@ -264,13 +266,13 @@ export default function Header ({ sub }) {
|
|||
className={`${styles.navbarNav}`}
|
||||
activeKey={topNavKey}
|
||||
>
|
||||
<NavItems className='mr-1' prefix={prefix} sub={sub} />
|
||||
<NavItems className='me-1' prefix={prefix} sub={sub} />
|
||||
<Link href={prefix + '/search'} passHref legacyBehavior>
|
||||
<Nav.Link eventKey='search' className='position-relative ml-auto d-flex mr-1'>
|
||||
<Nav.Link eventKey='search' className='position-relative ms-auto d-flex me-1'>
|
||||
<SearchIcon className='theme' width={22} height={22} />
|
||||
</Nav.Link>
|
||||
</Link>
|
||||
<PostItem className='mr-0 pr-0' prefix={prefix} />
|
||||
<PostItem className='me-0' prefix={prefix} />
|
||||
</Nav>
|
||||
</Navbar>
|
||||
</Container>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
line-height: 100%;
|
||||
margin-bottom: -.3rem;
|
||||
margin-right: 0;
|
||||
text-shadow: 0 0 10px var(--primary);
|
||||
text-shadow: 0 0 10px var(--bs-primary);
|
||||
color: var(--theme-brandColor) !important;
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,14 @@
|
|||
fill: var(--theme-navLinkActive);
|
||||
}
|
||||
|
||||
.dropdown svg {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.jobIndicator {
|
||||
position: absolute;
|
||||
padding: .25rem;
|
||||
background-color: var(--primary);
|
||||
background-color: var(--bs-primary);
|
||||
top: 3px;
|
||||
right: 0px;
|
||||
border: 1px solid var(--theme-body);
|
||||
|
@ -40,8 +44,8 @@
|
|||
.notification {
|
||||
position: absolute;
|
||||
padding: .25rem;
|
||||
background-color: var(--danger);
|
||||
top: 3px;
|
||||
background-color: var(--bs-danger);
|
||||
top: 1px;
|
||||
right: 8px;
|
||||
border: 1px solid var(--theme-body);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ export default function Info ({ children, iconClassName = 'fill-theme-color' })
|
|||
|
||||
return (
|
||||
<InfoIcon
|
||||
width={18} height={18} className={`${iconClassName} pointer ml-1`}
|
||||
width={18} height={18} className={`${iconClassName} pointer ms-1`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
showModal(onClose => children)
|
||||
|
|
|
@ -6,7 +6,7 @@ function InvoiceDefaultStatus ({ status }) {
|
|||
return (
|
||||
<div className='d-flex mt-2 justify-content-center'>
|
||||
<Moon className='spin fill-grey' />
|
||||
<div className='ml-3 text-muted' style={{ fontWeight: '600' }}>{status}</div>
|
||||
<div className='ms-3 text-muted' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ function InvoiceConfirmedStatus ({ status }) {
|
|||
return (
|
||||
<div className='d-flex mt-2 justify-content-center'>
|
||||
<Check className='fill-success' />
|
||||
<div className='ml-3 text-success' style={{ fontWeight: '600' }}>{status}</div>
|
||||
<div className='ms-3 text-success' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ function InvoiceFailedStatus ({ status }) {
|
|||
return (
|
||||
<div className='d-flex mt-2 justify-content-center'>
|
||||
<ThumbDown className='fill-danger' />
|
||||
<div className='ml-3 text-danger' style={{ fontWeight: '600' }}>{status}</div>
|
||||
<div className='ms-3 text-danger' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Button, InputGroup } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import React, { useState, useRef, useEffect } from 'react'
|
||||
import { Form, Input, SubmitButton } from './form'
|
||||
import { useMe } from './me'
|
||||
|
@ -12,12 +13,12 @@ const Tips = ({ setOValue }) => {
|
|||
return tips.map(num =>
|
||||
<Button
|
||||
size='sm'
|
||||
className={`${num > 1 ? 'ml-2' : ''} mb-2`}
|
||||
className={`${num > 1 ? 'ms-2' : ''} mb-2`}
|
||||
key={num}
|
||||
onClick={() => { setOValue(num) }}
|
||||
>
|
||||
<UpBolt
|
||||
className='mr-1'
|
||||
className='me-1'
|
||||
width={14}
|
||||
height={14}
|
||||
/>{num}
|
||||
|
@ -77,7 +78,7 @@ export default function ItemAct ({ onClose, itemId, act, strike }) {
|
|||
<Tips setOValue={setOValue} />
|
||||
</div>
|
||||
<div className='d-flex'>
|
||||
<SubmitButton variant='success' className='ml-auto mt-1 px-4' value='TIP'>zap</SubmitButton>
|
||||
<SubmitButton variant='success' className='ms-auto mt-1 px-4' value='TIP'>zap</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ import styles from '../styles/item.module.css'
|
|||
import itemStyles from './item.module.css'
|
||||
import { NOFOLLOW_LIMIT } from '../lib/constants'
|
||||
import { useMe } from './me'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { TwitterTweetEmbed } from 'react-twitter-embed'
|
||||
import YouTube from 'react-youtube'
|
||||
import useDarkMode from './dark-mode'
|
||||
|
@ -134,7 +134,7 @@ function TopLevelItem ({ item, noReply, ...props }) {
|
|||
{item.url && <ItemEmbed item={item} />}
|
||||
{item.poll && <Poll item={item} />}
|
||||
{item.bounty &&
|
||||
<div className='font-weight-bold mt-2'>
|
||||
<div className='fw-bold mt-2'>
|
||||
{item.bountyPaidTo?.length
|
||||
? (
|
||||
<div className='px-3 py-1 d-inline-block bg-grey-medium rounded text-success'>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Badge, Dropdown } from 'react-bootstrap'
|
||||
import Badge from 'react-bootstrap/Badge'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import Countdown from './countdown'
|
||||
import { abbrNum } from '../lib/format'
|
||||
import { newComments } from '../lib/new-comments'
|
||||
|
@ -43,12 +44,12 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, class
|
|||
</>}
|
||||
<Link href={`/items/${item.id}`} title={`${item.commentSats} sats`} className='text-reset'>
|
||||
{item.ncomments} {commentsText || 'comments'}
|
||||
{hasNewComments && <>{' '}<Badge className={styles.newComment} variant={null}>new</Badge></>}
|
||||
{hasNewComments && <>{' '}<Badge className={styles.newComment} bg={null}>new</Badge></>}
|
||||
</Link>
|
||||
<span> \ </span>
|
||||
<span>
|
||||
<Link href={`/${item.user.name}`} className='d-inline-flex align-items-center'>
|
||||
@{item.user.name}<CowboyHat className='ml-1 fill-grey' user={item.user} height={12} width={12} />
|
||||
<Link href={`/${item.user.name}`}>
|
||||
@{item.user.name}<CowboyHat className='ms-1 fill-grey' user={item.user} height={12} width={12} />
|
||||
{embellishUser}
|
||||
</Link>
|
||||
<span> </span>
|
||||
|
@ -65,15 +66,15 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, class
|
|||
</span>
|
||||
{item.subName &&
|
||||
<Link href={`/~${item.subName}`}>
|
||||
{' '}<Badge className={styles.newComment} variant={null}>{item.subName}</Badge>
|
||||
{' '}<Badge className={styles.newComment} bg={null}>{item.subName}</Badge>
|
||||
</Link>}
|
||||
{(item.outlawed && !item.mine &&
|
||||
<Link href='/recent/outlawed'>
|
||||
{' '}<Badge className={styles.newComment} variant={null}>outlawed</Badge>
|
||||
{' '}<Badge className={styles.newComment} bg={null}>outlawed</Badge>
|
||||
</Link>) ||
|
||||
(item.freebie &&
|
||||
<Link href='/recent/freebies'>
|
||||
{' '}<Badge className={styles.newComment} variant={null}>freebie</Badge>
|
||||
{' '}<Badge className={styles.newComment} bg={null}>freebie</Badge>
|
||||
</Link>
|
||||
)}
|
||||
{canEdit && !item.deletedAt &&
|
||||
|
@ -112,9 +113,9 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, class
|
|||
|
||||
export function ItemDropdown ({ children }) {
|
||||
return (
|
||||
<Dropdown className='pointer' as='span'>
|
||||
<Dropdown.Toggle variant='success' id='dropdown-basic' as='a'>
|
||||
<MoreIcon className='fill-grey ml-1' height={16} width={16} />
|
||||
<Dropdown className={`pointer ${styles.dropdown}`} as='span'>
|
||||
<Dropdown.Toggle variant='success' as='a'>
|
||||
<MoreIcon className='fill-grey ms-1' height={16} width={16} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{children}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import * as Yup from 'yup'
|
||||
import Toc from './table-of-contents'
|
||||
import { Badge, Button, Image } from 'react-bootstrap'
|
||||
import Badge from 'react-bootstrap/Badge'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { SearchTitle } from './item'
|
||||
import styles from './item.module.css'
|
||||
import Link from 'next/link'
|
||||
|
@ -28,7 +30,7 @@ export default function ItemJob ({ item, toc, rank, children }) {
|
|||
</Link>
|
||||
<div className={`${styles.hunk} align-self-center mb-0`}>
|
||||
<div className={`${styles.main} flex-wrap d-inline`}>
|
||||
<Link href={`/items/${item.id}`} className={`${styles.title} text-reset mr-2`}>
|
||||
<Link href={`/items/${item.id}`} className={`${styles.title} text-reset me-2`}>
|
||||
{item.searchTitle
|
||||
? <SearchTitle title={item.searchTitle} />
|
||||
: (
|
||||
|
@ -49,7 +51,7 @@ export default function ItemJob ({ item, toc, rank, children }) {
|
|||
<span> \ </span>
|
||||
<span>
|
||||
<Link href={`/${item.user.name}`} className='d-inline-flex align-items-center'>
|
||||
@{item.user.name}<CowboyHat className='ml-1 fill-grey' user={item.user} height={12} width={12} />
|
||||
@{item.user.name}<CowboyHat className='ms-1 fill-grey' user={item.user} height={12} width={12} />
|
||||
</Link>
|
||||
<span> </span>
|
||||
<Link href={`/items/${item.id}`} title={item.createdAt} className='text-reset'>
|
||||
|
@ -64,9 +66,9 @@ export default function ItemJob ({ item, toc, rank, children }) {
|
|||
<Link href={`/items/${item.id}/edit`} className='text-reset'>
|
||||
edit
|
||||
</Link>
|
||||
{item.status !== 'ACTIVE' && <span className='ml-1 font-weight-bold text-boost'> {item.status}</span>}
|
||||
{item.status !== 'ACTIVE' && <span className='ms-1 fw-bold text-boost'> {item.status}</span>}
|
||||
</>)}
|
||||
{item.maxBid > 0 && item.status === 'ACTIVE' && <Badge className={`${styles.newComment} ml-1`}>PROMOTED</Badge>}
|
||||
{item.maxBid > 0 && item.status === 'ACTIVE' && <Badge className={`${styles.newComment} ms-1`}>PROMOTED</Badge>}
|
||||
</div>
|
||||
</div>
|
||||
{toc &&
|
||||
|
@ -81,9 +83,9 @@ export default function ItemJob ({ item, toc, rank, children }) {
|
|||
<Button
|
||||
target='_blank' href={isEmail ? `mailto:${item.url}?subject=${encodeURIComponent(item.title)} via Stacker News` : item.url}
|
||||
>
|
||||
apply {isEmail && <EmailIcon className='ml-1' />}
|
||||
apply {isEmail && <EmailIcon className='ms-1' />}
|
||||
</Button>
|
||||
{isEmail && <div className='ml-3 align-self-center text-muted font-weight-bold'>{item.url}</div>}
|
||||
{isEmail && <div className='ms-3 align-self-center text-muted fw-bold'>{item.url}</div>}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -39,22 +39,22 @@ export default function Item ({ item, rank, belowTitle, right, full, children, s
|
|||
: item.meDontLike ? <Flag width={24} height={24} className={`${styles.dontLike}`} /> : <UpVote item={item} className={styles.upvote} pendingSats={pendingSats} setPendingSats={setPendingSats} />}
|
||||
<div className={styles.hunk}>
|
||||
<div className={`${styles.main} flex-wrap`}>
|
||||
<Link href={`/items/${item.id}`} ref={titleRef} className={`${styles.title} text-reset mr-2`}>
|
||||
<Link href={`/items/${item.id}`} ref={titleRef} className={`${styles.title} text-reset me-2`}>
|
||||
{item.searchTitle ? <SearchTitle title={item.searchTitle} /> : item.title}
|
||||
{item.pollCost && <span className={styles.icon}> <PollIcon className='fill-grey ml-1' height={14} width={14} /></span>}
|
||||
{item.pollCost && <span className={styles.icon}> <PollIcon className='fill-grey ms-1' height={14} width={14} /></span>}
|
||||
{item.bounty > 0 &&
|
||||
<span className={styles.icon}>
|
||||
<ActionTooltip notForm overlayText={`${abbrNum(item.bounty)} ${item.bountyPaidTo?.length ? 'sats paid' : 'sats bounty'}`}>
|
||||
<BountyIcon className={`${styles.bountyIcon} ${item.bountyPaidTo?.length ? 'fill-success' : 'fill-grey'}`} height={16} width={16} />
|
||||
</ActionTooltip>
|
||||
</span>}
|
||||
{image && <span className={styles.icon}><ImageIcon className='fill-grey ml-2' height={16} width={16} /></span>}
|
||||
{image && <span className={styles.icon}><ImageIcon className='fill-grey ms-2' height={16} width={16} /></span>}
|
||||
</Link>
|
||||
{item.url && !image &&
|
||||
<>
|
||||
{/* eslint-disable-next-line */}
|
||||
<a
|
||||
className={`${styles.link} py-half py-md-0`} target='_blank' href={item.url}
|
||||
className={`${styles.link}`} target='_blank' href={item.url}
|
||||
rel={item.sats + item.boost >= NOFOLLOW_LIMIT ? null : 'nofollow'}
|
||||
>
|
||||
{item.url.replace(/(^https?:|^)\/\//, '')}
|
||||
|
@ -88,7 +88,7 @@ export function ItemSkeleton ({ rank, children }) {
|
|||
<UpVote className={styles.upvote} />
|
||||
<div className={styles.hunk}>
|
||||
<div className={`${styles.main} flex-wrap flex-md-nowrap`}>
|
||||
<span className={`${styles.title} clouds text-reset flex-md-fill flex-md-shrink-0 mr-2`} />
|
||||
<span className={`${styles.title} clouds text-reset flex-md-fill flex-md-shrink-0 me-2`} />
|
||||
<span className={`${styles.link} clouds`} />
|
||||
</div>
|
||||
<div className={styles.other}>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
max-width: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding-bottom: .15rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
@ -24,12 +25,15 @@ a.title:visited {
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1 0 128px;
|
||||
padding-bottom: .15rem;
|
||||
}
|
||||
|
||||
.newComment {
|
||||
color: var(--theme-grey) !important;
|
||||
background: var(--theme-clickToContextColor) !important;
|
||||
vertical-align: middle;
|
||||
margin-top: -1px;
|
||||
margin-left: 0.1rem;
|
||||
}
|
||||
|
||||
.pin {
|
||||
|
@ -64,6 +68,16 @@ a.link:visited {
|
|||
.other {
|
||||
font-size: 80%;
|
||||
color: var(--theme-grey);
|
||||
vertical-align: text-top;
|
||||
margin-bottom: .125rem;
|
||||
}
|
||||
|
||||
.other svg {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.other .dropdown svg {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.item {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { Checkbox, Form, Input, MarkdownInput, SubmitButton } from './form'
|
||||
import { InputGroup, Form as BForm, Col, Image } from 'react-bootstrap'
|
||||
import Row from 'react-bootstrap/Row'
|
||||
import Col from 'react-bootstrap/Col'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import BootstrapForm from 'react-bootstrap/Form'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Info from './info'
|
||||
import AccordianItem from './accordian-item'
|
||||
|
@ -9,8 +14,6 @@ import { useRouter } from 'next/router'
|
|||
import Link from 'next/link'
|
||||
import { usePrice } from './price'
|
||||
import Avatar from './avatar'
|
||||
import BootstrapForm from 'react-bootstrap/Form'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import ActionTooltip from './action-tooltip'
|
||||
import { jobSchema } from '../lib/validate'
|
||||
import CancelButton from './cancel-button'
|
||||
|
@ -115,7 +118,7 @@ export default function JobForm ({ item, sub }) {
|
|||
required
|
||||
clear
|
||||
/>
|
||||
<BForm.Row className='mr-0'>
|
||||
<Row className='me-0'>
|
||||
<Col>
|
||||
<Input
|
||||
label='location'
|
||||
|
@ -124,10 +127,10 @@ export default function JobForm ({ item, sub }) {
|
|||
/>
|
||||
</Col>
|
||||
<Checkbox
|
||||
label={<div className='font-weight-bold'>remote</div>} name='remote' hiddenLabel
|
||||
label={<div className='fw-bold'>remote</div>} name='remote' hiddenLabel
|
||||
groupClassName={styles.inlineCheckGroup}
|
||||
/>
|
||||
</BForm.Row>
|
||||
</Row>
|
||||
<MarkdownInput
|
||||
topLevel
|
||||
label='description'
|
||||
|
@ -136,7 +139,7 @@ export default function JobForm ({ item, sub }) {
|
|||
required
|
||||
/>
|
||||
<Input
|
||||
label={<>how to apply <small className='text-muted ml-2'>url or email address</small></>}
|
||||
label={<>how to apply <small className='text-muted ms-2'>url or email address</small></>}
|
||||
name='url'
|
||||
required
|
||||
clear
|
||||
|
@ -187,14 +190,14 @@ function PromoteJob ({ item, sub, storageKeyPrefix }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>bid
|
||||
<Info>
|
||||
<ol className='font-weight-bold'>
|
||||
<ol className='fw-bold'>
|
||||
<li>The higher your bid the higher your job will rank</li>
|
||||
<li>You can increase, decrease, or remove your bid at anytime</li>
|
||||
<li>You can edit or stop your job at anytime</li>
|
||||
<li>If you run out of sats, your job will stop being promoted until you fill your wallet again</li>
|
||||
</ol>
|
||||
</Info>
|
||||
<small className='text-muted ml-2'>optional</small>
|
||||
<small className='text-muted ms-2'>optional</small>
|
||||
</div>
|
||||
}
|
||||
name='maxBid'
|
||||
|
@ -210,7 +213,7 @@ function PromoteJob ({ item, sub, storageKeyPrefix }) {
|
|||
hint={<PriceHint monthly={monthly} />}
|
||||
storageKeyPrefix={storageKeyPrefix}
|
||||
/>
|
||||
<><div className='font-weight-bold text-muted'>This bid puts your job in position: {position}</div></>
|
||||
<><div className='fw-bold text-muted'>This bid puts your job in position: {position}</div></>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
@ -227,10 +230,10 @@ function StatusControl ({ item }) {
|
|||
|
||||
<AccordianItem
|
||||
header={<div style={{ fontWeight: 'bold', fontSize: '92%' }}>I want to stop my job</div>}
|
||||
headerColor='var(--danger)'
|
||||
headerColor='var(--bs-danger)'
|
||||
body={
|
||||
<Checkbox
|
||||
label={<div className='font-weight-bold text-danger'>stop my job</div>} name='stop' inline
|
||||
label={<div className='fw-bold text-danger'>stop my job</div>} name='stop' inline
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
@ -242,10 +245,10 @@ function StatusControl ({ item }) {
|
|||
return (
|
||||
<AccordianItem
|
||||
header={<div style={{ fontWeight: 'bold', fontSize: '92%' }}>I want to resume my job</div>}
|
||||
headerColor='var(--success)'
|
||||
headerColor='var(--bs-success)'
|
||||
body={
|
||||
<Checkbox
|
||||
label={<div className='font-weight-bold text-success'>resume my job</div>} name='start' inline
|
||||
label={<div className='fw-bold text-success'>resume my job</div>} name='start' inline
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||
import { signIn } from 'next-auth/client'
|
||||
import { useEffect } from 'react'
|
||||
import { Col, Container, Row } from 'react-bootstrap'
|
||||
import Col from 'react-bootstrap/Col'
|
||||
import Container from 'react-bootstrap/Container'
|
||||
import Row from 'react-bootstrap/Row'
|
||||
import AccordianItem from './accordian-item'
|
||||
import Qr, { QrSkeleton } from './qr'
|
||||
import styles from './lightning-auth.module.css'
|
||||
|
@ -37,9 +39,9 @@ function LightningExplainer ({ text, children }) {
|
|||
<h3 className='w-100 pb-2'>
|
||||
{text || 'Login'} with Lightning
|
||||
</h3>
|
||||
<div className='font-weight-bold text-muted pb-4'>This is the most private way to use Stacker News. Just open your Lightning wallet and scan the QR code.</div>
|
||||
<div className='fw-bold text-muted pb-4'>This is the most private way to use Stacker News. Just open your Lightning wallet and scan the QR code.</div>
|
||||
<Row className='w-100 text-muted'>
|
||||
<Col className='pl-0 mb-4' md>
|
||||
<Col className='ps-0 mb-4' md>
|
||||
<AccordianItem
|
||||
header={`Which wallets can I use to ${(text || 'Login').toLowerCase()}?`}
|
||||
body={
|
||||
|
|
|
@ -9,7 +9,7 @@ import Item from './item'
|
|||
import AccordianItem from './accordian-item'
|
||||
import FeeButton, { EditFeeButton } from './fee-button'
|
||||
import Delete from './delete'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { linkSchema } from '../lib/validate'
|
||||
import Moon from '../svgs/moon-fill.svg'
|
||||
import { SubSelectInitial } from './sub-select-form'
|
||||
|
@ -143,7 +143,7 @@ export function LinkForm ({ item, sub, editThreshold, children }) {
|
|||
autoComplete='off'
|
||||
overrideValue={data?.pageTitleAndUnshorted?.unshorted}
|
||||
hint={editThreshold
|
||||
? <div className='text-muted font-weight-bold'><Countdown date={editThreshold} /></div>
|
||||
? <div className='text-muted fw-bold'><Countdown date={editThreshold} /></div>
|
||||
: null}
|
||||
onChange={async (formik, e) => {
|
||||
if ((/^ *$/).test(formik?.values.title)) {
|
||||
|
@ -191,9 +191,9 @@ export function LinkForm ({ item, sub, editThreshold, children }) {
|
|||
ChildButton={SubmitButton} variant='secondary'
|
||||
/>
|
||||
{dupesLoading &&
|
||||
<div className='d-flex ml-3 justify-content-center'>
|
||||
<div className='d-flex ms-3 justify-content-center'>
|
||||
<Moon className='spin fill-grey' />
|
||||
<div className='ml-2 text-muted' style={{ fontWeight: '600' }}>searching for dupes</div>
|
||||
<div className='ms-2 text-muted' style={{ fontWeight: '600' }}>searching for dupes</div>
|
||||
</div>}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -2,7 +2,7 @@ import GithubIcon from '../svgs/github-fill.svg'
|
|||
import TwitterIcon from '../svgs/twitter-fill.svg'
|
||||
import LightningIcon from '../svgs/bolt.svg'
|
||||
import SlashtagsIcon from '../svgs/slashtags.svg'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
|
||||
export default function LoginButton ({ text, type, className, onClick }) {
|
||||
let Icon, variant
|
||||
|
@ -32,7 +32,7 @@ export default function LoginButton ({ text, type, className, onClick }) {
|
|||
<Button className={className} variant={variant} onClick={onClick}>
|
||||
<Icon
|
||||
width={20}
|
||||
height={20} className='mr-3'
|
||||
height={20} className='me-3'
|
||||
/>
|
||||
{text} {name}
|
||||
</Button>
|
||||
|
|
|
@ -71,7 +71,7 @@ export default function Login ({ providers, callbackUrl, error, text, Header, Fo
|
|||
case 'Email':
|
||||
return (
|
||||
<div className='w-100' key={provider.name}>
|
||||
<div className='mt-2 text-center text-muted font-weight-bold'>or</div>
|
||||
<div className='mt-2 text-center text-muted fw-bold'>or</div>
|
||||
<EmailLoginForm text={text} callbackUrl={callbackUrl} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { createContext, useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { Modal } from 'react-bootstrap'
|
||||
import Modal from 'react-bootstrap/Modal'
|
||||
|
||||
export const ShowModalContext = createContext(() => null)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
|
||||
|
@ -40,7 +40,7 @@ export function NavigateFooter ({ cursor, count, fetchMore, href, text, noMoreTe
|
|||
let Footer
|
||||
if (cursor) {
|
||||
Footer = () => (
|
||||
<Link href={href} className='text-reset text-muted font-weight-bold'>{text}</Link>
|
||||
<Link href={href} className='text-reset text-muted fw-bold'>{text}</Link>
|
||||
)
|
||||
} else {
|
||||
Footer = () => (
|
||||
|
|
|
@ -15,7 +15,7 @@ import { COMMENT_DEPTH_LIMIT } from '../lib/constants'
|
|||
import CowboyHatIcon from '../svgs/cowboy.svg'
|
||||
import BaldIcon from '../svgs/bald.svg'
|
||||
import { RootProvider } from './root'
|
||||
import { Alert } from 'react-bootstrap'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import styles from './notifications.module.css'
|
||||
import { useServiceWorker } from './serviceworker'
|
||||
import { Checkbox, Form } from './form'
|
||||
|
@ -110,9 +110,9 @@ function Streak ({ n }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className='d-flex font-weight-bold ml-2 py-1'>
|
||||
<div className='d-flex fw-bold ms-2 py-1'>
|
||||
<div style={{ fontSize: '2rem' }}>{n.days ? <BaldIcon className='fill-grey' height={40} width={40} /> : <CowboyHatIcon className='fill-grey' height={40} width={40} />}</div>
|
||||
<div className='ml-1 p-1'>
|
||||
<div className='ms-1 p-1'>
|
||||
you {n.days ? 'lost your' : 'found a'} cowboy hat
|
||||
<div><small style={{ lineHeight: '140%', display: 'inline-block' }}>{blurb(n)}</small></div>
|
||||
</div>
|
||||
|
@ -122,11 +122,11 @@ function Streak ({ n }) {
|
|||
|
||||
function EarnNotification ({ n }) {
|
||||
return (
|
||||
<div className='d-flex ml-2 py-1'>
|
||||
<div className='d-flex ms-2 py-1'>
|
||||
<HandCoin className='align-self-center fill-boost mx-1' width={24} height={24} style={{ flex: '0 0 24px', transform: 'rotateY(180deg)' }} />
|
||||
<div className='ml-2'>
|
||||
<div className='font-weight-bold text-boost'>
|
||||
you stacked {n.earnedSats} sats in rewards<small className='text-muted ml-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
<div className='ms-2'>
|
||||
<div className='fw-bold text-boost'>
|
||||
you stacked {n.earnedSats} sats in rewards<small className='text-muted ms-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
</div>
|
||||
{n.sources &&
|
||||
<div style={{ fontSize: '80%', color: 'var(--theme-grey)' }}>
|
||||
|
@ -146,10 +146,10 @@ function EarnNotification ({ n }) {
|
|||
function Invitification ({ n }) {
|
||||
return (
|
||||
<NotificationLayout href='/invites'>
|
||||
<small className='font-weight-bold text-secondary ml-2'>
|
||||
<small className='fw-bold text-secondary ms-2'>
|
||||
your invite has been redeemed by {n.invite.invitees.length} stackers
|
||||
</small>
|
||||
<div className='ml-4 mr-2 mt-1'>
|
||||
<div className='ms-4 me-2 mt-1'>
|
||||
<Invite
|
||||
invite={n.invite} active={
|
||||
!n.invite.revoked &&
|
||||
|
@ -164,9 +164,9 @@ function Invitification ({ n }) {
|
|||
function InvoicePaid ({ n }) {
|
||||
return (
|
||||
<NotificationLayout href={`/invoices/${n.invoice.id}`}>
|
||||
<div className='font-weight-bold text-info ml-2 py-1'>
|
||||
<Check className='fill-info mr-1' />{n.earnedSats} sats were deposited in your account
|
||||
<small className='text-muted ml-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
<div className='fw-bold text-info ms-2 py-1'>
|
||||
<Check className='fill-info me-1' />{n.earnedSats} sats were deposited in your account
|
||||
<small className='text-muted ms-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
</div>
|
||||
</NotificationLayout>
|
||||
)
|
||||
|
@ -175,9 +175,9 @@ function InvoicePaid ({ n }) {
|
|||
function Referral ({ n }) {
|
||||
return (
|
||||
<NotificationLayout>
|
||||
<small className='font-weight-bold text-secondary ml-2'>
|
||||
<small className='fw-bold text-secondary ms-2'>
|
||||
someone joined via one of your <Link href='/referrals/month' className='text-reset'>referral links</Link>
|
||||
<small className='text-muted ml-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
<small className='text-muted ms-1'>{timeSince(new Date(n.sortTime))}</small>
|
||||
</small>
|
||||
</NotificationLayout>
|
||||
)
|
||||
|
@ -186,7 +186,7 @@ function Referral ({ n }) {
|
|||
function Votification ({ n }) {
|
||||
return (
|
||||
<NotificationLayout {...defaultOnClick(n)}>
|
||||
<small className='font-weight-bold text-success ml-2'>
|
||||
<small className='fw-bold text-success ms-2'>
|
||||
your {n.item.title ? 'post' : 'reply'} {n.item.fwdUser ? 'forwarded' : 'stacked'} {n.earnedSats} sats{n.item.fwdUser && ` to @${n.item.fwdUser.name}`}
|
||||
</small>
|
||||
<div>
|
||||
|
@ -207,7 +207,7 @@ function Votification ({ n }) {
|
|||
function Mention ({ n }) {
|
||||
return (
|
||||
<NotificationLayout {...defaultOnClick(n)}>
|
||||
<small className='font-weight-bold text-info ml-2'>
|
||||
<small className='fw-bold text-info ms-2'>
|
||||
you were mentioned in
|
||||
</small>
|
||||
<div>
|
||||
|
@ -227,7 +227,7 @@ function Mention ({ n }) {
|
|||
function JobChanged ({ n }) {
|
||||
return (
|
||||
<NotificationLayout {...defaultOnClick(n)}>
|
||||
<small className={`font-weight-bold text-${n.item.status === 'ACTIVE' ? 'success' : 'boost'} ml-1`}>
|
||||
<small className={`fw-bold text-${n.item.status === 'ACTIVE' ? 'success' : 'boost'} ms-1`}>
|
||||
{n.item.status === 'ACTIVE'
|
||||
? 'your job is active again'
|
||||
: (n.item.status === 'NOSATS'
|
||||
|
@ -306,7 +306,7 @@ function NotificationAlert () {
|
|||
<Form className={`d-flex justify-content-end ${supported ? 'visible' : 'invisible'}`} initial={{ pushNotify: hasSubscription }}>
|
||||
<Checkbox
|
||||
name='pushNotify' label={<span className='text-muted'>push notifications</span>}
|
||||
groupClassName={`${styles.subFormGroup} mb-1 mr-sm-3 mr-0`}
|
||||
groupClassName={`${styles.subFormGroup} mb-1 me-sm-3 me-0`}
|
||||
inline checked={hasSubscription} handleChange={async () => {
|
||||
await sw.togglePushSubscription().catch(setError)
|
||||
}}
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function PastBounties ({ item }) {
|
|||
|
||||
return (
|
||||
<AccordianItem
|
||||
header={<div className='font-weight-bold'>{item.user.name}'s bounties</div>}
|
||||
header={<div className='fw-bold'>{item.user.name}'s bounties</div>}
|
||||
body={
|
||||
<Items
|
||||
variables={variables}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import styles from './pay-bounty.module.css'
|
||||
import ActionTooltip from './action-tooltip'
|
||||
import { useMutation, gql } from '@apollo/client'
|
||||
|
@ -96,7 +96,7 @@ export default function PayBounty ({ children, item }) {
|
|||
className={styles.pay} onClick={() => {
|
||||
showModal(onClose => (
|
||||
<>
|
||||
<div className='text-center font-weight-bold text-muted'>
|
||||
<div className='text-center fw-bold text-muted'>
|
||||
Pay this bounty to {item.user.name}?
|
||||
</div>
|
||||
<div className='text-center'>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.pay {
|
||||
color: var(--success);
|
||||
color: var(--bs-success);
|
||||
margin-left: 1rem;
|
||||
}
|
|
@ -6,7 +6,7 @@ import AdvPostForm, { AdvPostInitial } from './adv-post-form'
|
|||
import { MAX_POLL_NUM_CHOICES } from '../lib/constants'
|
||||
import FeeButton, { EditFeeButton } from './fee-button'
|
||||
import Delete from './delete'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { pollSchema } from '../lib/validate'
|
||||
import { SubSelectInitial } from './sub-select-form'
|
||||
import CancelButton from './cancel-button'
|
||||
|
@ -71,7 +71,7 @@ export function PollForm ({ item, sub, editThreshold, children }) {
|
|||
/>
|
||||
<MarkdownInput
|
||||
topLevel
|
||||
label={<>text <small className='text-muted ml-2'>optional</small></>}
|
||||
label={<>text <small className='text-muted ms-2'>optional</small></>}
|
||||
name='text'
|
||||
minRows={2}
|
||||
/>
|
||||
|
@ -82,7 +82,7 @@ export function PollForm ({ item, sub, editThreshold, children }) {
|
|||
max={MAX_POLL_NUM_CHOICES}
|
||||
min={2}
|
||||
hint={editThreshold
|
||||
? <div className='text-muted font-weight-bold'><Countdown date={editThreshold} /></div>
|
||||
? <div className='text-muted fw-bold'><Countdown date={editThreshold} /></div>
|
||||
: null}
|
||||
/>
|
||||
<AdvPostForm edit={!!item} />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { gql, useMutation } from '@apollo/client'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { fixedDecimal } from '../lib/format'
|
||||
import { timeLeft } from '../lib/time'
|
||||
import { useMe } from './me'
|
||||
|
@ -94,8 +94,8 @@ export default function Poll ({ item }) {
|
|||
function PollResult ({ v, progress }) {
|
||||
return (
|
||||
<div className={styles.pollResult}>
|
||||
<span className={styles.pollOption}>{v.option}{v.meVoted && <Check className='fill-grey ml-1 align-self-center' width={18} height={18} />}</span>
|
||||
<span className='ml-auto mr-2 align-self-center'>{progress}%</span>
|
||||
<span className={styles.pollOption}>{v.option}{v.meVoted && <Check className='fill-grey ms-1 align-self-center' width={18} height={18} />}</span>
|
||||
<span className='ms-auto me-2 align-self-center'>{progress}%</span>
|
||||
<div className={styles.pollProgress} style={{ width: `${progress}%` }} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.pollButton {
|
||||
margin-top: .25rem;
|
||||
display: block;
|
||||
border: 2px solid var(--info);
|
||||
border: 2px solid var(--bs-info);
|
||||
border-radius: 2rem;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import JobForm from './job-form'
|
||||
import Link from 'next/link'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import AccordianItem from './accordian-item'
|
||||
import { useMe } from './me'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -16,7 +16,7 @@ function FreebieDialog () {
|
|||
<div className='text-center mb-4 text-muted'>
|
||||
you have no sats, so this one is on us
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>Free posts have limited visibility and are hidden on the recent tab until other stackers zap them.</li>
|
||||
<li>Free posts will not cover posts that cost more than 1 sat.</li>
|
||||
<li>To get fully visibile and unrestricted posts right away, fund your account with a few sats or earn some on Stacker News.</li>
|
||||
|
@ -39,20 +39,20 @@ export function PostForm ({ type, sub, children }) {
|
|||
<Link href={prefix + '/post?type=link'}>
|
||||
<Button variant='secondary'>link</Button>
|
||||
</Link>
|
||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||
<span className='mx-3 fw-bold text-muted'>or</span>
|
||||
<Link href={prefix + '/post?type=discussion'}>
|
||||
<Button variant='secondary'>discussion</Button>
|
||||
</Link>
|
||||
<div className='d-flex mt-4'>
|
||||
<AccordianItem
|
||||
headerColor='#6c757d'
|
||||
header={<div className='font-weight-bold text-muted'>more types</div>}
|
||||
header={<div className='fw-bold text-muted'>more types</div>}
|
||||
body={
|
||||
<div className='align-items-center'>
|
||||
<Link href={prefix + '/post?type=poll'}>
|
||||
<Button variant='info'>poll</Button>
|
||||
</Link>
|
||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||
<span className='mx-3 fw-bold text-muted'>or</span>
|
||||
<Link href={prefix + '/post?type=bounty'}>
|
||||
<Button variant='info'>bounty</Button>
|
||||
</Link>
|
||||
|
|
|
@ -14,9 +14,9 @@ export default function RecentHeader ({ type, sub }) {
|
|||
type: router.query.type || type || 'posts'
|
||||
}}
|
||||
>
|
||||
<div className='text-muted font-weight-bold mt-0 mb-3 d-flex justify-content-end align-items-center'>
|
||||
<div className='text-muted fw-bold mt-0 mb-3 d-flex justify-content-end align-items-center'>
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
className='w-auto'
|
||||
name='type'
|
||||
size='sm'
|
||||
|
|
|
@ -10,7 +10,7 @@ export default function Related ({ title, itemId }) {
|
|||
|
||||
return (
|
||||
<AccordianItem
|
||||
header={<div className='font-weight-bold'>related</div>}
|
||||
header={<div className='fw-bold'>related</div>}
|
||||
body={
|
||||
<Items
|
||||
query={RELATED_ITEMS}
|
||||
|
|
|
@ -23,7 +23,7 @@ function FreebieDialog () {
|
|||
<div className='text-muted'>
|
||||
you have no sats, so this one is on us
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>Free comments have limited visibility and are listed at the bottom of the comment section until other stackers zap them.</li>
|
||||
<li>Free comments will not cover comments that cost more than 1 sat.</li>
|
||||
<li>To get fully visibile and unrestricted comments right away, fund your account with a few sats or earn some on Stacker News.</li>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding-bottom: .5rem;
|
||||
padding: .25rem 0 .5rem 0;
|
||||
line-height: 1rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Button, Container } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Container from 'react-bootstrap/Container'
|
||||
import styles from './search.module.css'
|
||||
import SearchIcon from '../svgs/search-line.svg'
|
||||
import CloseIcon from '../svgs/close-line.svg'
|
||||
|
@ -57,7 +58,7 @@ export default function Search ({ sub }) {
|
|||
return (
|
||||
<>
|
||||
<div className={`${styles.searchSection} ${showSearch ? styles.solid : styles.hidden}`}>
|
||||
<Container className={`px-sm-0 ${styles.searchContainer} ${filter ? styles.leaveRoom : ''}`}>
|
||||
<Container className={`px-md-0 ${styles.searchContainer} ${filter ? styles.leaveRoom : ''}`}>
|
||||
{showSearch
|
||||
? (
|
||||
<Form
|
||||
|
@ -71,9 +72,9 @@ export default function Search ({ sub }) {
|
|||
onSubmit={search}
|
||||
>
|
||||
{filter &&
|
||||
<div className='text-muted font-weight-bold my-3 d-flex align-items-center'>
|
||||
<div className='text-muted fw-bold my-3 d-flex align-items-center'>
|
||||
<Select
|
||||
groupClassName='mr-2 mb-0'
|
||||
groupClassName='me-2 mb-0'
|
||||
onChange={(formik, e) => search({ ...formik?.values, what: e.target.value })}
|
||||
name='what'
|
||||
size='sm'
|
||||
|
@ -91,7 +92,7 @@ export default function Search ({ sub }) {
|
|||
/>
|
||||
for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
onChange={(formik, e) => search({ ...formik?.values, when: e.target.value })}
|
||||
name='when'
|
||||
size='sm'
|
||||
|
@ -105,7 +106,7 @@ export default function Search ({ sub }) {
|
|||
name='q'
|
||||
required
|
||||
autoFocus
|
||||
groupClassName='mr-3 mb-0 flex-grow-1'
|
||||
groupClassName='me-3 mb-0 flex-grow-1'
|
||||
className='flex-grow-1'
|
||||
clear
|
||||
onChange={async (formik, e) => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Dropdown } from 'react-bootstrap'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import ShareIcon from '../svgs/share-fill.svg'
|
||||
import copy from 'clipboard-copy'
|
||||
import { useMe } from './me'
|
||||
|
@ -9,7 +9,7 @@ export default function Share ({ item }) {
|
|||
|
||||
return typeof window !== 'undefined' && navigator?.share
|
||||
? (
|
||||
<div className='ml-auto pointer d-flex align-items-center'>
|
||||
<div className='ms-auto pointer d-flex align-items-center'>
|
||||
<ShareIcon
|
||||
width={20} height={20}
|
||||
className='mx-2 fill-grey theme'
|
||||
|
@ -28,7 +28,7 @@ export default function Share ({ item }) {
|
|||
/>
|
||||
</div>)
|
||||
: (
|
||||
<Dropdown alignRight className='ml-auto pointer d-flex align-items-center' as='span'>
|
||||
<Dropdown align='end' className='ms-auto pointer d-flex align-items-center' as='span'>
|
||||
<Dropdown.Toggle variant='success' id='dropdown-basic' as='a'>
|
||||
<ShareIcon width={20} height={20} className='mx-2 fill-grey theme' />
|
||||
</Dropdown.Toggle>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Alert } from 'react-bootstrap'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import YouTube from '../svgs/youtube-line.svg'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { gql, useQuery } from '@apollo/client'
|
||||
|
@ -24,7 +24,7 @@ export default function Snl ({ ignorePreference }) {
|
|||
return (
|
||||
<div className='d-flex'>
|
||||
<Alert
|
||||
variant='info' className='font-weight-bold mb-3 d-flex py-2 flex-shrink align-items-center'
|
||||
variant='info' className='fw-bold mb-3 d-flex py-2 flex-shrink align-items-center'
|
||||
onClose={() => {
|
||||
setShow(undefined)
|
||||
localStorage.setItem('snl', new Date())
|
||||
|
@ -32,7 +32,7 @@ export default function Snl ({ ignorePreference }) {
|
|||
dismissible
|
||||
>
|
||||
<a href='https://www.youtube.com/@stackernews/live'>
|
||||
<YouTube width={24} height={24} className='mr-2 fill-info' />Stacker News Live is streaming this week's top stories
|
||||
<YouTube width={24} height={24} className='me-2 fill-info' />Stacker News Live is streaming this week's top stories
|
||||
</a>
|
||||
</Alert>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,7 @@ export default function SubSelect ({ label, sub, setSub, item, ...props }) {
|
|||
const SubInfo = () => (
|
||||
<Info>
|
||||
<div>
|
||||
<div className='font-weight-bold'>The sub your post will go in ...</div>
|
||||
<div className='fw-bold'>The sub your post will go in ...</div>
|
||||
<ul>
|
||||
<li>If it's bitcoin related, put it in the bitcoin sub.</li>
|
||||
<li>If it's nostr related, put it in the nostr sub.</li>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMutation } from '@apollo/client'
|
||||
import { gql } from 'graphql-tag'
|
||||
import { Dropdown } from 'react-bootstrap'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
|
||||
export default function SubscribeDropdownItem ({ item: { id, meSubscription } }) {
|
||||
const [subscribeItem] = useMutation(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useMemo, useState } from 'react'
|
||||
import { Dropdown, FormControl } from 'react-bootstrap'
|
||||
import Dropdown from 'react-bootstrap/Dropdown'
|
||||
import FormControl from 'react-bootstrap/FormControl'
|
||||
import TocIcon from '../svgs/list-unordered.svg'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { visit } from 'unist-util-visit'
|
||||
|
@ -27,7 +28,7 @@ export default function Toc ({ text }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<Dropdown alignRight className='d-flex align-items-center'>
|
||||
<Dropdown align='end' className='d-flex align-items-center'>
|
||||
<Dropdown.Toggle as={CustomToggle} id='dropdown-custom-components'>
|
||||
<TocIcon width={20} height={20} className='mx-2 fill-grey theme' />
|
||||
</Dropdown.Toggle>
|
||||
|
@ -36,7 +37,7 @@ export default function Toc ({ text }) {
|
|||
{toc.map(v => {
|
||||
return (
|
||||
<Dropdown.Item
|
||||
className={v.depth === 1 ? 'font-weight-bold' : ''}
|
||||
className={v.depth === 1 ? 'fw-bold' : ''}
|
||||
style={{
|
||||
marginLeft: `${(v.depth - 1) * 5}px`
|
||||
}}
|
||||
|
|
|
@ -201,8 +201,8 @@ export function ZoomableImage ({ src, topLevel, ...props }) {
|
|||
if (!src) return null
|
||||
if (err) {
|
||||
return (
|
||||
<span className='d-flex align-items-center text-warning font-weight-bold pb-1'>
|
||||
<FileMissing width={18} height={18} className='fill-warning mr-1' />
|
||||
<span className='d-flex align-items-center text-warning fw-bold pb-1'>
|
||||
<FileMissing width={18} height={18} className='fill-warning me-1' />
|
||||
broken image <small>stacker probably used an unreliable host</small>
|
||||
</span>
|
||||
)
|
||||
|
|
|
@ -34,7 +34,7 @@ export default function TopHeader ({ sub, cat }) {
|
|||
return (
|
||||
<div className='d-flex'>
|
||||
<Form
|
||||
className='mr-auto'
|
||||
className='me-auto'
|
||||
initial={{
|
||||
what: cat,
|
||||
by: router.query.by || '',
|
||||
|
@ -42,7 +42,7 @@ export default function TopHeader ({ sub, cat }) {
|
|||
}}
|
||||
onSubmit={top}
|
||||
>
|
||||
<div className='text-muted font-weight-bold my-3 d-flex align-items-center'>
|
||||
<div className='text-muted fw-bold my-3 d-flex align-items-center'>
|
||||
top
|
||||
<Select
|
||||
groupClassName='mx-2 mb-0'
|
||||
|
@ -63,7 +63,7 @@ export default function TopHeader ({ sub, cat }) {
|
|||
/>
|
||||
for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
onChange={(formik, e) => top({ ...formik?.values, when: e.target.value })}
|
||||
name='when'
|
||||
size='sm'
|
||||
|
|
|
@ -8,14 +8,15 @@ import { useMe } from './me'
|
|||
import Rainbow from '../lib/rainbow'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import LongPressable from 'react-longpressable'
|
||||
import { Overlay, Popover } from 'react-bootstrap'
|
||||
import Overlay from 'react-bootstrap/Overlay'
|
||||
import Popover from 'react-bootstrap/Popover'
|
||||
import { useShowModal } from './modal'
|
||||
import { useRouter } from 'next/router'
|
||||
import { LightningConsumer } from './lightning'
|
||||
|
||||
const getColor = (meSats) => {
|
||||
if (!meSats || meSats <= 10) {
|
||||
return 'var(--secondary)'
|
||||
return 'var(--bs-secondary)'
|
||||
}
|
||||
|
||||
const idx = Math.min(
|
||||
|
@ -33,13 +34,13 @@ const UpvotePopover = ({ target, show, handleClose }) => {
|
|||
placement='right'
|
||||
>
|
||||
<Popover id='popover-basic'>
|
||||
<Popover.Title className='d-flex justify-content-between alert-dismissible' as='h3'>Zapping
|
||||
<Popover.Body className='d-flex justify-content-between alert-dismissible' as='h3'>Zapping
|
||||
<button type='button' className='close' onClick={handleClose}><span aria-hidden='true'>×</span><span className='sr-only'>Close alert</span></button>
|
||||
</Popover.Title>
|
||||
<Popover.Content>
|
||||
</Popover.Body>
|
||||
<Popover.Body>
|
||||
<div className='mb-2'>Press the bolt again to zap {me?.tipDefault || 1} more sat{me?.tipDefault > 1 ? 's' : ''}.</div>
|
||||
<div>Repeatedly press the bolt to zap more sats.</div>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
</Overlay>
|
||||
)
|
||||
|
@ -52,13 +53,13 @@ const TipPopover = ({ target, show, handleClose }) => (
|
|||
placement='right'
|
||||
>
|
||||
<Popover id='popover-basic'>
|
||||
<Popover.Title className='d-flex justify-content-between alert-dismissible' as='h3'>Press and hold
|
||||
<Popover.Body className='d-flex justify-content-between alert-dismissible' as='h3'>Press and hold
|
||||
<button type='button' className='close' onClick={handleClose}><span aria-hidden='true'>×</span><span className='sr-only'>Close alert</span></button>
|
||||
</Popover.Title>
|
||||
<Popover.Content>
|
||||
</Popover.Body>
|
||||
<Popover.Body>
|
||||
<div className='mb-2'>Press and hold bolt to zap a custom amount.</div>
|
||||
<div>As you zap more, the bolt color follows the rainbow.</div>
|
||||
</Popover.Content>
|
||||
</Popover.Body>
|
||||
</Popover>
|
||||
</Overlay>
|
||||
)
|
||||
|
|
|
@ -11,10 +11,10 @@ export function UsageHeader () {
|
|||
when: router.query.when || 'day'
|
||||
}}
|
||||
>
|
||||
<div className='text-muted font-weight-bold my-3 d-flex align-items-center'>
|
||||
<div className='text-muted fw-bold my-3 d-flex align-items-center'>
|
||||
stacker analytics for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
className='w-auto'
|
||||
name='when'
|
||||
size='sm'
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { Button, InputGroup, Image } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import Nav from 'react-bootstrap/Nav'
|
||||
|
@ -158,23 +160,23 @@ function HeaderHeader ({ user }) {
|
|||
const showModal = useShowModal()
|
||||
|
||||
const isMe = me?.name === user.name
|
||||
const Satistics = () => <div className={`mb-2 ml-0 ml-sm-1 ${styles.username} text-success`}>{user.stacked} stacked</div>
|
||||
const Satistics = () => <div className={`mb-2 ms-0 ms-sm-1 ${styles.username} text-success`}>{user.stacked} stacked</div>
|
||||
|
||||
const lnurlp = encodeLNUrl(new URL(`https://stacker.news/.well-known/lnurlp/${user.name}`))
|
||||
return (
|
||||
<div className='d-flex mt-2 flex-wrap flex-column flex-sm-row'>
|
||||
<HeaderPhoto user={user} isMe={isMe} />
|
||||
<div className='ml-0 ml-sm-3 mt-3 mt-sm-0 justify-content-center align-self-sm-center'>
|
||||
<div className='ms-0 ms-sm-3 mt-3 mt-sm-0 justify-content-center align-self-sm-center'>
|
||||
<HeaderNym user={user} isMe={isMe} />
|
||||
<Satistics user={user} />
|
||||
<Button
|
||||
className='font-weight-bold ml-0' onClick={() => {
|
||||
className='fw-bold ms-0' onClick={() => {
|
||||
showModal(({ onClose }) => (
|
||||
<>
|
||||
<a className='d-flex m-auto p-3' style={{ background: 'white', width: 'fit-content' }} href={`lightning:${lnurlp}`}>
|
||||
<QRCode className='d-flex m-auto' value={lnurlp} renderAs='svg' size={300} />
|
||||
</a>
|
||||
<div className='text-center font-weight-bold text-muted mt-3'>click or scan</div>
|
||||
<div className='text-center fw-bold text-muted mt-3'>click or scan</div>
|
||||
</>
|
||||
))
|
||||
}}
|
||||
|
@ -182,12 +184,12 @@ function HeaderHeader ({ user }) {
|
|||
<LightningIcon
|
||||
width={20}
|
||||
height={20}
|
||||
className='mr-1'
|
||||
className='me-1'
|
||||
/>{user.name}@stacker.news
|
||||
</Button>
|
||||
<div className='d-flex flex-column mt-1 ml-0'>
|
||||
<div className='d-flex flex-column mt-1 ms-0'>
|
||||
<small className='text-muted d-flex-inline'>stacking since: {user.since
|
||||
? <Link href={`/items/${user.since}`} className='ml-1'>#{user.since}</Link>
|
||||
? <Link href={`/items/${user.since}`} className='ms-1'>#{user.since}</Link>
|
||||
: <span>never</span>}
|
||||
</small>
|
||||
<small className='text-muted d-flex-inline'>longest cowboy streak: {user.maxStreak !== null ? user.maxStreak : 'none'}</small>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
|
||||
.nav :global .active {
|
||||
border-bottom: 2px solid var(--primary);
|
||||
border-bottom: 2px solid var(--bs-primary);
|
||||
}
|
||||
|
||||
.userimg {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Link from 'next/link'
|
||||
import { Image } from 'react-bootstrap'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { abbrNum } from '../lib/format'
|
||||
import CowboyHat from './cowboy-hat'
|
||||
import styles from './item.module.css'
|
||||
|
@ -67,12 +67,12 @@ export default function UserList ({ ssrData, query, variables, destructureData }
|
|||
<Link href={`/${user.name}`}>
|
||||
<Image
|
||||
src={user.photoId ? `https://${process.env.NEXT_PUBLIC_AWS_UPLOAD_BUCKET}.s3.amazonaws.com/${user.photoId}` : '/dorian400.jpg'} width='32' height='32'
|
||||
className={`${userStyles.userimg} mr-2`}
|
||||
className={`${userStyles.userimg} me-2`}
|
||||
/>
|
||||
</Link>
|
||||
<div className={styles.hunk}>
|
||||
<Link href={`/${user.name}`} className={`${styles.title} d-inline-flex align-items-center text-reset`}>
|
||||
@{user.name}<CowboyHat className='ml-1 fill-grey' height={14} width={14} user={user} />
|
||||
@{user.name}<CowboyHat className='ms-1 fill-grey' height={14} width={14} user={user} />
|
||||
</Link>
|
||||
<div className={styles.other}>
|
||||
{statComps.map((Comp, i) => <Comp key={i} user={user} />)}
|
||||
|
@ -94,7 +94,7 @@ export function UsersSkeleton () {
|
|||
<Image
|
||||
src={`${process.env.NEXT_PUBLIC_ASSET_PREFIX}/clouds.jpeg`}
|
||||
width='32' height='32'
|
||||
className={`${userStyles.userimg} clouds mr-2`}
|
||||
className={`${userStyles.userimg} clouds me-2`}
|
||||
/>
|
||||
<div className={styles.hunk}>
|
||||
<div className={`${styles.name} clouds text-reset`} />
|
||||
|
|
|
@ -42,12 +42,12 @@ const transformData = data => {
|
|||
}
|
||||
|
||||
const COLORS = [
|
||||
'var(--secondary)',
|
||||
'var(--info)',
|
||||
'var(--success)',
|
||||
'var(--boost)',
|
||||
'var(--bs-secondary)',
|
||||
'var(--bs-info)',
|
||||
'var(--bs-success)',
|
||||
'var(--bs-boost)',
|
||||
'var(--theme-grey)',
|
||||
'var(--danger)'
|
||||
'var(--bs-danger)'
|
||||
]
|
||||
|
||||
export function WhenAreaChart ({ data }) {
|
||||
|
@ -150,7 +150,7 @@ export function WhenComposedChart ({ data, lineNames, areaNames, barNames }) {
|
|||
<Tooltip labelFormatter={dateFormatter(when)} contentStyle={{ color: 'var(--theme-color)', backgroundColor: 'var(--theme-body)' }} />
|
||||
<Legend />
|
||||
{barNames?.map((v, i) =>
|
||||
<Bar yAxisId='right' key={v} type='monotone' dataKey={v} name={v} stroke='var(--info)' fill='var(--info)' />)}
|
||||
<Bar yAxisId='right' key={v} type='monotone' dataKey={v} name={v} stroke='var(--bs-info)' fill='var(--bs-info)' />)}
|
||||
{areaNames?.map((v, i) =>
|
||||
<Area yAxisId='left' key={v} type='monotone' dataKey={v} name={v} stackId='1' stroke={COLORS[i]} fill={COLORS[i]} />)}
|
||||
{lineNames?.map((v, i) =>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"babel-plugin-inline-react-svg": "^2.0.1",
|
||||
"bech32": "^2.0.0",
|
||||
"bolt11": "^1.4.0",
|
||||
"bootstrap": "^4.6.2",
|
||||
"bootstrap": "^5.3.0",
|
||||
"browserslist": "^4.21.4",
|
||||
"canonical-json": "0.0.4",
|
||||
"clipboard-copy": "^4.0.1",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-avatar-editor": "^13.0.0",
|
||||
"react-bootstrap": "^1.6.6",
|
||||
"react-bootstrap": "^2.8.0",
|
||||
"react-countdown": "^2.3.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-longpressable": "^1.1.1",
|
||||
|
@ -2859,9 +2859,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
|
||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
|
@ -2952,6 +2952,17 @@
|
|||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||
},
|
||||
"node_modules/@react-aria/ssr": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz",
|
||||
"integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@remusao/guess-url-type": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@remusao/guess-url-type/-/guess-url-type-1.2.1.tgz",
|
||||
|
@ -2989,25 +3000,45 @@
|
|||
"resolved": "https://registry.npmjs.org/@remusao/trie/-/trie-1.4.1.tgz",
|
||||
"integrity": "sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q=="
|
||||
},
|
||||
"node_modules/@restart/context": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
|
||||
"integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/hooks": {
|
||||
"version": "0.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.7.tgz",
|
||||
"integrity": "sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==",
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz",
|
||||
"integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.2"
|
||||
"dequal": "^2.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/ui": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz",
|
||||
"integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@react-aria/ssr": "^3.5.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dequal": "^2.0.3",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"uncontrollable": "^8.0.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.14.0",
|
||||
"react-dom": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@restart/ui/node_modules/uncontrollable": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz",
|
||||
"integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||
|
@ -3475,11 +3506,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
|
||||
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
|
||||
},
|
||||
"node_modules/@types/invariant": {
|
||||
"version": "2.2.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
||||
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
|
||||
|
@ -4903,9 +4929,9 @@
|
|||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
|
||||
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
@ -4917,8 +4943,7 @@
|
|||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"jquery": "1.9.1 - 3",
|
||||
"popper.js": "^1.16.1"
|
||||
"@popperjs/core": "^2.11.7"
|
||||
}
|
||||
},
|
||||
"node_modules/bplist-parser": {
|
||||
|
@ -14227,31 +14252,42 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-bootstrap": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.6.tgz",
|
||||
"integrity": "sha512-pSzYyJT5u4rc8+5myM8Vid2JG52L8AmYSkpznReH/GM4+FhLqEnxUa0+6HRTaGwjdEixQNGchwY+b3xCdYWrDA==",
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz",
|
||||
"integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.14.0",
|
||||
"@restart/context": "^2.1.4",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/invariant": "^2.2.33",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/react": ">=16.14.8",
|
||||
"@types/react-transition-group": "^4.4.1",
|
||||
"@types/warning": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@restart/ui": "^1.6.3",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"classnames": "^2.3.2",
|
||||
"dom-helpers": "^5.2.1",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"prop-types": "^15.8.1",
|
||||
"prop-types-extra": "^1.1.0",
|
||||
"react-overlays": "^5.1.2",
|
||||
"react-transition-group": "^4.4.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
"@types/react": ">=16.14.8",
|
||||
"react": ">=16.14.0",
|
||||
"react-dom": ">=16.14.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-bootstrap/node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-countdown": {
|
||||
|
@ -14337,25 +14373,6 @@
|
|||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/react-overlays": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
|
||||
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.3.0",
|
||||
"react-dom": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-resize-detector": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.1.0.tgz",
|
||||
|
@ -20797,9 +20814,9 @@
|
|||
}
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
|
||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
|
||||
},
|
||||
"@prisma/client": {
|
||||
"version": "2.30.3",
|
||||
|
@ -20873,6 +20890,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||
},
|
||||
"@react-aria/ssr": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.7.0.tgz",
|
||||
"integrity": "sha512-bfufjg4ESE5giN+Fxj1XIzS5f/YIhqcGc+Ve+vUUKU8xZ8t/Xtjlv8F3kjqDBQdk//n3mluFY7xG1wQVB9rMLQ==",
|
||||
"requires": {
|
||||
"@swc/helpers": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"@remusao/guess-url-type": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@remusao/guess-url-type/-/guess-url-type-1.2.1.tgz",
|
||||
|
@ -20910,17 +20935,35 @@
|
|||
"resolved": "https://registry.npmjs.org/@remusao/trie/-/trie-1.4.1.tgz",
|
||||
"integrity": "sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q=="
|
||||
},
|
||||
"@restart/context": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
|
||||
"integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
|
||||
},
|
||||
"@restart/hooks": {
|
||||
"version": "0.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.7.tgz",
|
||||
"integrity": "sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==",
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz",
|
||||
"integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==",
|
||||
"requires": {
|
||||
"dequal": "^2.0.2"
|
||||
"dequal": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"@restart/ui": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz",
|
||||
"integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@react-aria/ssr": "^3.5.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dequal": "^2.0.3",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"uncontrollable": "^8.0.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"uncontrollable": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz",
|
||||
"integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
|
@ -21347,11 +21390,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
|
||||
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
|
||||
},
|
||||
"@types/invariant": {
|
||||
"version": "2.2.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz",
|
||||
"integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
|
||||
|
@ -22521,9 +22559,9 @@
|
|||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ=="
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.0.tgz",
|
||||
"integrity": "sha512-UnBV3E3v4STVNQdms6jSGO2CvOkjUMdDAVR2V5N4uCMdaIkaQjbcEAMqRimDHIs4uqBYzDAKCQwCB+97tJgHQw=="
|
||||
},
|
||||
"bplist-parser": {
|
||||
"version": "0.2.0",
|
||||
|
@ -29311,27 +29349,34 @@
|
|||
}
|
||||
},
|
||||
"react-bootstrap": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.6.tgz",
|
||||
"integrity": "sha512-pSzYyJT5u4rc8+5myM8Vid2JG52L8AmYSkpznReH/GM4+FhLqEnxUa0+6HRTaGwjdEixQNGchwY+b3xCdYWrDA==",
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.8.0.tgz",
|
||||
"integrity": "sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.14.0",
|
||||
"@restart/context": "^2.1.4",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/invariant": "^2.2.33",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/react": ">=16.14.8",
|
||||
"@types/react-transition-group": "^4.4.1",
|
||||
"@types/warning": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@restart/hooks": "^0.4.9",
|
||||
"@restart/ui": "^1.6.3",
|
||||
"@types/react-transition-group": "^4.4.5",
|
||||
"classnames": "^2.3.2",
|
||||
"dom-helpers": "^5.2.1",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"prop-types": "^15.8.1",
|
||||
"prop-types-extra": "^1.1.0",
|
||||
"react-overlays": "^5.1.2",
|
||||
"react-transition-group": "^4.4.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-countdown": {
|
||||
|
@ -29400,21 +29445,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"react-overlays": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
|
||||
"integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.8",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@restart/hooks": "^0.4.7",
|
||||
"@types/warning": "^3.0.0",
|
||||
"dom-helpers": "^5.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"uncontrollable": "^7.2.1",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-resize-detector": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.1.0.tgz",
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"babel-plugin-inline-react-svg": "^2.0.1",
|
||||
"bech32": "^2.0.0",
|
||||
"bolt11": "^1.4.0",
|
||||
"bootstrap": "^4.6.2",
|
||||
"bootstrap": "^5.3.0",
|
||||
"browserslist": "^4.21.4",
|
||||
"canonical-json": "0.0.4",
|
||||
"clipboard-copy": "^4.0.1",
|
||||
|
@ -59,7 +59,7 @@
|
|||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-avatar-editor": "^13.0.0",
|
||||
"react-bootstrap": "^1.6.6",
|
||||
"react-bootstrap": "^2.8.0",
|
||||
"react-countdown": "^2.3.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-longpressable": "^1.1.1",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Image } from 'react-bootstrap'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { StaticLayout } from '../components/layout'
|
||||
import styles from '../styles/404.module.css'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Image } from 'react-bootstrap'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { StaticLayout } from '../components/layout'
|
||||
import styles from '../styles/404.module.css'
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ function UserItemsHeader ({ type, name }) {
|
|||
}}
|
||||
onSubmit={select}
|
||||
>
|
||||
<div className='text-muted font-weight-bold mt-0 mb-3 d-flex justify-content-start align-items-center'>
|
||||
<div className='text-muted fw-bold mt-0 mb-3 d-flex justify-content-start align-items-center'>
|
||||
<Select
|
||||
groupClassName='mb-0 mr-2'
|
||||
groupClassName='mb-0 me-2'
|
||||
className='w-auto'
|
||||
name='type'
|
||||
size='sm'
|
||||
|
@ -80,7 +80,7 @@ function UserItemsHeader ({ type, name }) {
|
|||
/>
|
||||
for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
className='w-auto'
|
||||
name='when'
|
||||
size='sm'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Layout from '../../components/layout'
|
||||
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||
import UserHeader from '../../components/user-header'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import styles from '../../styles/user.module.css'
|
||||
import { useState } from 'react'
|
||||
import ItemFull from '../../components/item-full'
|
||||
|
|
|
@ -14,14 +14,16 @@ import ErrorBoundary from '../components/error-boundary'
|
|||
import { LightningProvider } from '../components/lightning'
|
||||
import { ServiceWorkerProvider } from '../components/serviceworker'
|
||||
|
||||
const SSR = typeof window === 'undefined'
|
||||
|
||||
function writeQuery (client, apollo, data) {
|
||||
if (apollo && data) {
|
||||
client.writeQuery({
|
||||
query: gql`${apollo.query}`,
|
||||
data: data,
|
||||
variables: apollo.variables,
|
||||
broadcast: false,
|
||||
overwrite: true
|
||||
broadcast: !SSR,
|
||||
overwrite: SSR
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +56,7 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
|||
*/
|
||||
const { apollo, ssrData, me, price, ...otherProps } = props
|
||||
// if we are on the server, useEffect won't run
|
||||
if (typeof window === 'undefined' && client) {
|
||||
if (SSR && client) {
|
||||
writeQuery(client, apollo, ssrData)
|
||||
}
|
||||
useEffect(() => {
|
||||
|
@ -64,7 +66,7 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
|||
return (
|
||||
<>
|
||||
<NextNProgress
|
||||
color='var(--primary)'
|
||||
color='var(--bs-primary)'
|
||||
startPosition={0.3}
|
||||
stopDelayMs={200}
|
||||
height={2}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Image } from 'react-bootstrap'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { StaticLayout } from '../components/layout'
|
||||
|
||||
export default function Email () {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Layout from '../../components/layout'
|
||||
import { Form, Input, SubmitButton } from '../../components/form'
|
||||
import { InputGroup } from 'react-bootstrap'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||
import { INVITE_FIELDS } from '../../fragments/invites'
|
||||
import AccordianItem from '../../components/accordian-item'
|
||||
|
@ -58,7 +58,7 @@ function InviteForm () {
|
|||
required
|
||||
/>
|
||||
<Input
|
||||
label={<>invitee limit <small className='text-muted ml-2'>optional</small></>}
|
||||
label={<>invitee limit <small className='text-muted ms-2'>optional</small></>}
|
||||
name='limit'
|
||||
/>
|
||||
|
||||
|
@ -113,7 +113,7 @@ export default function Invites () {
|
|||
<h2 className='mt-3 mb-0'>
|
||||
invite links
|
||||
</h2>
|
||||
<small className='d-block text-muted font-weight-bold mx-5'>send these to people you trust, e.g. group chats or DMs</small>
|
||||
<small className='d-block text-muted fw-bold mx-5'>send these to people you trust, e.g. group chats or DMs</small>
|
||||
</div>
|
||||
<InviteForm />
|
||||
{active.length > 0 && <InviteList name='active' invites={active} />}
|
||||
|
|
|
@ -2,7 +2,7 @@ import Layout from '../../../components/layout'
|
|||
import { ITEM_OTS } from '../../../fragments/items'
|
||||
import { getGetServerSideProps } from '../../../api/ssrApollo'
|
||||
import stringifyCanon from 'canonical-json'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { useQuery } from '@apollo/client'
|
||||
import { useRouter } from 'next/router'
|
||||
import PageLoading from '../../../components/page-loading'
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function Related ({ ssrData }) {
|
|||
return (
|
||||
<Layout>
|
||||
<Item item={item} />
|
||||
<div className='font-weight-bold my-2'>related</div>
|
||||
<div className='fw-bold my-2'>related</div>
|
||||
<Items
|
||||
ssrData={ssrData}
|
||||
query={RELATED_ITEMS}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Button } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import { CenterLayout } from '../components/layout'
|
||||
import Snl from '../components/snl'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
|
|
@ -39,7 +39,7 @@ export async function getServerSideProps ({ req, res, query: { callbackUrl, erro
|
|||
|
||||
function LoginFooter ({ callbackUrl }) {
|
||||
return (
|
||||
<small className='font-weight-bold text-muted pt-4'>Don't have an account? <Link href={{ pathname: '/signup', query: { callbackUrl } }}>sign up</Link></small>
|
||||
<small className='fw-bold text-muted pt-4'>Don't have an account? <Link href={{ pathname: '/signup', query: { callbackUrl } }}>sign up</Link></small>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Image } from 'react-bootstrap'
|
||||
import Image from 'react-bootstrap/Image'
|
||||
import { StaticLayout } from '../components/layout'
|
||||
import styles from '../styles/404.module.css'
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ export default function Referrals ({ ssrData }) {
|
|||
const { data } = useQuery(REFERRALS, { variables: { when: router.query.when } })
|
||||
if (!data && !ssrData) return <PageLoading />
|
||||
|
||||
const { referrals: { totalSats, totalReferrals, stats } } = data
|
||||
const { referrals: { totalSats, totalReferrals, stats } } = data || ssrData
|
||||
|
||||
return (
|
||||
<CenterLayout footerLinks>
|
||||
|
@ -44,10 +44,10 @@ export default function Referrals ({ ssrData }) {
|
|||
when: router.query.when
|
||||
}}
|
||||
>
|
||||
<h4 className='font-weight-bold text-muted text-center pt-5 pb-3 d-flex align-items-center justify-content-center'>
|
||||
<h4 className='fw-bold text-muted text-center pt-5 pb-3 d-flex align-items-center justify-content-center'>
|
||||
{totalReferrals} referrals & {totalSats} sats in the last
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
groupClassName='mb-0 ms-2'
|
||||
className='w-auto'
|
||||
name='when'
|
||||
size='sm'
|
||||
|
@ -61,7 +61,7 @@ export default function Referrals ({ ssrData }) {
|
|||
<div
|
||||
className='text-small pt-5 px-3 d-flex w-100 align-items-center'
|
||||
>
|
||||
<div className='nav-item text-muted pr-2' style={{ 'white-space': 'nowrap' }}>referral link:</div>
|
||||
<div className='nav-item text-muted pe-2' style={{ 'white-space': 'nowrap' }}>referral link:</div>
|
||||
<CopyInput
|
||||
size='sm'
|
||||
groupClassName='mb-0 w-100'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { gql } from 'graphql-tag'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Button, InputGroup } from 'react-bootstrap'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts'
|
||||
import { getGetServerSideProps } from '../api/ssrApollo'
|
||||
import { Form, Input, SubmitButton } from '../components/form'
|
||||
|
@ -68,7 +69,7 @@ export default function Rewards ({ ssrData }) {
|
|||
|
||||
return (
|
||||
<CenterLayout footerLinks>
|
||||
<h4 className='font-weight-bold text-muted text-center'>
|
||||
<h4 className='fw-bold text-muted text-center'>
|
||||
<div>
|
||||
<RewardLine total={total} />
|
||||
</div>
|
||||
|
@ -85,11 +86,11 @@ export default function Rewards ({ ssrData }) {
|
|||
}
|
||||
|
||||
const COLORS = [
|
||||
'var(--secondary)',
|
||||
'var(--info)',
|
||||
'var(--success)',
|
||||
'var(--boost)',
|
||||
'var(--grey)'
|
||||
'var(--bs-secondary)',
|
||||
'var(--bs-info)',
|
||||
'var(--bs-success)',
|
||||
'var(--bs-boost)',
|
||||
'var(--bs-grey)'
|
||||
]
|
||||
|
||||
function GrowthPieChart ({ data }) {
|
||||
|
@ -103,7 +104,7 @@ function GrowthPieChart ({ data }) {
|
|||
cx='50%'
|
||||
cy='50%'
|
||||
outerRadius={80}
|
||||
fill='var(--secondary)'
|
||||
fill='var(--bs-secondary)'
|
||||
label
|
||||
>
|
||||
{
|
||||
|
@ -151,7 +152,7 @@ export function DonateButton () {
|
|||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||
/>
|
||||
<div className='d-flex'>
|
||||
<SubmitButton variant='success' className='ml-auto mt-1 px-4' value='TIP'>donate</SubmitButton>
|
||||
<SubmitButton variant='success' className='ms-auto mt-1 px-4' value='TIP'>donate</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
))}
|
||||
|
|
|
@ -79,7 +79,7 @@ function Satus ({ status }) {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Icon /><small className={`text-${color} font-weight-bold ml-2`}>{desc}</small>
|
||||
<Icon /><small className={`text-${color} fw-bold ms-2`}>{desc}</small>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { Checkbox, Form, Input, SubmitButton, Select, VariableInput } from '../components/form'
|
||||
import { Alert, Button, InputGroup } from 'react-bootstrap'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import { CenterLayout } from '../components/layout'
|
||||
import { useState } from 'react'
|
||||
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||
|
@ -113,7 +115,7 @@ export default function Settings ({ ssrData }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>turbo zapping
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>Makes every additional bolt click raise your total zap to another 10x multiple of your default zap</li>
|
||||
<li>e.g. if your zap default is 10 sats
|
||||
<ul>
|
||||
|
@ -188,7 +190,7 @@ export default function Settings ({ ssrData }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>hide invoice descriptions
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>Use this if you don't want funding sources to be linkable to your SN identity.</li>
|
||||
<li>It makes your invoice descriptions blank.</li>
|
||||
<li>This only applies to invoices you create
|
||||
|
@ -217,7 +219,7 @@ export default function Settings ({ ssrData }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>wild west mode
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>don't hide flagged content</li>
|
||||
<li>don't down rank flagged content</li>
|
||||
</ul>
|
||||
|
@ -231,7 +233,7 @@ export default function Settings ({ ssrData }) {
|
|||
label={
|
||||
<div className='d-flex align-items-center'>greeter mode
|
||||
<Info>
|
||||
<ul className='font-weight-bold'>
|
||||
<ul className='fw-bold'>
|
||||
<li>see and screen free posts and comments</li>
|
||||
<li>help onboard new stackers to SN and Lightning</li>
|
||||
<li>you might be subject to more spam</li>
|
||||
|
@ -244,16 +246,16 @@ export default function Settings ({ ssrData }) {
|
|||
<AccordianItem
|
||||
headerColor='var(--theme-color)'
|
||||
show={settings?.nostrPubkey}
|
||||
header={<h4 className='mb-2 text-left'>nostr <small><a href='https://github.com/nostr-protocol/nips/blob/master/05.md' target='_blank' rel='noreferrer'>NIP-05</a></small></h4>}
|
||||
header={<h4 className='text-left'>nostr <small><a href='https://github.com/nostr-protocol/nips/blob/master/05.md' target='_blank' rel='noreferrer'>NIP-05</a></small></h4>}
|
||||
body={
|
||||
<>
|
||||
<Input
|
||||
label={<>pubkey <small className='text-muted ml-2'>optional</small></>}
|
||||
label={<>pubkey <small className='text-muted ms-2'>optional</small></>}
|
||||
name='nostrPubkey'
|
||||
clear
|
||||
/>
|
||||
<VariableInput
|
||||
label={<>relays <small className='text-muted ml-2'>optional</small></>}
|
||||
label={<>relays <small className='text-muted ms-2'>optional</small></>}
|
||||
name='nostrRelays'
|
||||
clear
|
||||
min={0}
|
||||
|
@ -263,7 +265,7 @@ export default function Settings ({ ssrData }) {
|
|||
}
|
||||
/>
|
||||
<div className='d-flex'>
|
||||
<SubmitButton variant='info' className='ml-auto mt-1 px-4'>save</SubmitButton>
|
||||
<SubmitButton variant='info' className='ms-auto mt-1 px-4'>save</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
<div className='text-left w-100'>
|
||||
|
@ -301,7 +303,7 @@ function UnlinkObstacle ({ onClose, type, unlinkAuth }) {
|
|||
<div>
|
||||
You are removing your last auth method. It is recommended you link another auth method before removing
|
||||
your last auth method. If you'd like to proceed anyway, type the following below
|
||||
<div className='text-danger font-weight-bold my-2'>
|
||||
<div className='text-danger fw-bold my-2'>
|
||||
If I logout, even accidentally, I will never be able to access my account again
|
||||
</div>
|
||||
<Form
|
||||
|
@ -320,7 +322,7 @@ function UnlinkObstacle ({ onClose, type, unlinkAuth }) {
|
|||
name='warning'
|
||||
required
|
||||
/>
|
||||
<SubmitButton className='d-flex ml-auto' variant='danger'>do it</SubmitButton>
|
||||
<SubmitButton className='d-flex ms-auto' variant='danger'>do it</SubmitButton>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
|
@ -379,7 +381,7 @@ function AuthMethods ({ methods }) {
|
|||
noForm
|
||||
/>
|
||||
<Button
|
||||
className='ml-2' variant='secondary' onClick={
|
||||
className='ms-2' variant='secondary' onClick={
|
||||
async () => {
|
||||
await unlink('email')
|
||||
}
|
||||
|
@ -448,7 +450,7 @@ export function EmailLinkForm ({ callbackUrl }) {
|
|||
required
|
||||
groupClassName='mb-0'
|
||||
/>
|
||||
<SubmitButton className='ml-2' variant='secondary'>Link Email</SubmitButton>
|
||||
<SubmitButton className='ms-2' variant='secondary'>Link Email</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
|
|
|
@ -9,14 +9,14 @@ function SignUpHeader () {
|
|||
<h3 className='w-100 pb-2'>
|
||||
Sign up
|
||||
</h3>
|
||||
<div className='font-weight-bold text-muted pb-4'>Join 15,000+ bitcoiners and start stacking sats today</div>
|
||||
<div className='fw-bold text-muted pb-4'>Join 15,000+ bitcoiners and start stacking sats today</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SignUpFooter ({ callbackUrl }) {
|
||||
return (
|
||||
<small className='font-weight-bold text-muted pt-4'>Already have an account? <Link href={{ pathname: '/login', query: { callbackUrl } }}>login</Link></small>
|
||||
<small className='fw-bold text-muted pt-4'>Already have an account? <Link href={{ pathname: '/login', query: { callbackUrl } }}>login</Link></small>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { gql } from '@apollo/client'
|
||||
import { getGetServerSideProps } from '../../api/ssrApollo'
|
||||
import Layout from '../../components/layout'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import Col from 'react-bootstrap/Col'
|
||||
import Row from 'react-bootstrap/Row'
|
||||
import { UsageHeader } from '../../components/usage-header'
|
||||
import { WhenLineChart, WhenAreaChart } from '../../components/when-charts'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -65,31 +66,31 @@ export default function Growth ({
|
|||
<UsageHeader />
|
||||
<Row>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>{avg}stackers</div>
|
||||
<div className='text-center text-muted fw-bold'>{avg}stackers</div>
|
||||
<WhenLineChart data={stackerGrowth} />
|
||||
</Col>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>stacking</div>
|
||||
<div className='text-center text-muted fw-bold'>stacking</div>
|
||||
<WhenAreaChart data={stackingGrowth} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>{avg}spenders</div>
|
||||
<div className='text-center text-muted fw-bold'>{avg}spenders</div>
|
||||
<WhenLineChart data={spenderGrowth} />
|
||||
</Col>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>spending</div>
|
||||
<div className='text-center text-muted fw-bold'>spending</div>
|
||||
<WhenAreaChart data={spendingGrowth} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>registrations</div>
|
||||
<div className='text-center text-muted fw-bold'>registrations</div>
|
||||
<WhenAreaChart data={registrationGrowth} />
|
||||
</Col>
|
||||
<Col className='mt-3'>
|
||||
<div className='text-center text-muted font-weight-bold'>items</div>
|
||||
<div className='text-center text-muted fw-bold'>items</div>
|
||||
<WhenAreaChart data={itemGrowth} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { WithdrawlSkeleton } from './withdrawals/[id]'
|
|||
import { useMe } from '../components/me'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { requestProvider } from 'webln'
|
||||
import { Alert } from 'react-bootstrap'
|
||||
import Alert from 'react-bootstrap/Alert'
|
||||
import { CREATE_WITHDRAWL, SEND_TO_LNADDR } from '../fragments/wallet'
|
||||
import { getGetServerSideProps } from '../api/ssrApollo'
|
||||
import { amountSchema, lnAddrSchema, withdrawlSchema } from '../lib/validate'
|
||||
|
@ -37,7 +37,7 @@ function YouHaveSats () {
|
|||
function WalletHistory () {
|
||||
return (
|
||||
<div className='pt-4'>
|
||||
<Link href='/satistics?inc=invoice,withdrawal' className='text-muted font-weight-bold text-underline'>
|
||||
<Link href='/satistics?inc=invoice,withdrawal' className='text-muted fw-bold text-underline'>
|
||||
wallet history
|
||||
</Link>
|
||||
</div>
|
||||
|
@ -54,7 +54,7 @@ export function WalletForm () {
|
|||
<Link href='/wallet?type=fund'>
|
||||
<Button variant='success'>fund</Button>
|
||||
</Link>
|
||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||
<span className='mx-3 fw-bold text-muted'>or</span>
|
||||
<Link href='/wallet?type=withdraw'>
|
||||
<Button variant='success'>withdraw</Button>
|
||||
</Link>
|
||||
|
@ -189,7 +189,7 @@ export function WithdrawlForm () {
|
|||
/>
|
||||
<SubmitButton variant='success' className='mt-2'>withdraw</SubmitButton>
|
||||
</Form>
|
||||
<span className='my-3 font-weight-bold text-muted'>or via</span>
|
||||
<span className='my-3 fw-bold text-muted'>or via</span>
|
||||
<Link href='/wallet?type=lnurl-withdraw'>
|
||||
<Button variant='grey'>QR code</Button>
|
||||
</Link>
|
||||
|
|
|
@ -43,7 +43,7 @@ function LoadWithdrawl () {
|
|||
|
||||
const TryMaxFee = () =>
|
||||
<Link href='/wallet?type=withdraw' className='text-reset text-underline'>
|
||||
<small className='ml-3'>try increasing max fee</small>
|
||||
<small className='ms-3'>try increasing max fee</small>
|
||||
</Link>
|
||||
|
||||
let status = 'pending'
|
||||
|
@ -54,7 +54,7 @@ function LoadWithdrawl () {
|
|||
variant = 'confirmed'
|
||||
break
|
||||
case 'INSUFFICIENT_BALANCE':
|
||||
status = <>insufficient balance <small className='ml-3'>contact keyan!</small></>
|
||||
status = <>insufficient balance <small className='ms-3'>contact keyan!</small></>
|
||||
variant = 'failed'
|
||||
break
|
||||
case 'INVALID_PAYMENT':
|
||||
|
|
|
@ -25,7 +25,7 @@ export default function Index ({ ssrData }) {
|
|||
/>
|
||||
: (
|
||||
<div className='text-muted text-center mt-5' style={{ fontFamily: 'lightning', fontSize: '2rem', opacity: '0.75' }}>
|
||||
<Down width={22} height={22} className='mr-2' />search for something<Down width={22} height={22} className='ml-2' />
|
||||
<Down width={22} height={22} className='me-2' />search for something<Down width={22} height={22} className='ms-2' />
|
||||
</div>)}
|
||||
</SearchLayout>
|
||||
)
|
||||
|
|
|
@ -37,7 +37,7 @@ const COLORS = {
|
|||
commentBg: 'rgba(255, 255, 255, 0.04)',
|
||||
clickToContextColor: 'rgba(255, 255, 255, 0.2)',
|
||||
color: '#f8f9fa',
|
||||
brandColor: 'var(--primary)',
|
||||
brandColor: 'var(--bs-primary)',
|
||||
grey: '#969696',
|
||||
link: '#2e99d1',
|
||||
toolbarActive: 'rgba(255, 255, 255, 0.10)',
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
$primary: #FADA5E;
|
||||
$secondary: #F6911D;
|
||||
$danger: #c03221;
|
||||
$info: #007cbe;
|
||||
$success: #5c8001;
|
||||
$twitter: #1da1f2;
|
||||
$boost: #8c25f4;
|
||||
$light: #f8f9fa;
|
||||
$dark: #212529;
|
||||
|
||||
$theme-colors: (
|
||||
"primary" : #FADA5E,
|
||||
"secondary" : #F6911D,
|
||||
|
@ -6,9 +16,11 @@ $theme-colors: (
|
|||
"success" : #5c8001,
|
||||
"twitter" : #1da1f2,
|
||||
"boost" : #8c25f4,
|
||||
"light": #f8f9fa,
|
||||
"dark": #212529,
|
||||
"grey" : #e9ecef,
|
||||
"grey-medium" : #d2d2d2,
|
||||
"grey-darkmode": #8c8c8c
|
||||
"grey-darkmode": #8c8c8c,
|
||||
);
|
||||
|
||||
$body-bg: #f5f5f7;
|
||||
|
@ -20,6 +32,7 @@ $btn-transition: none;
|
|||
$form-feedback-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M2 9h3v12H2a1 1 0 0 1-1-1V10a1 1 0 0 1 1-1zm5.293-1.293l6.4-6.4a.5.5 0 0 1 .654-.047l.853.64a1.5 1.5 0 0 1 .553 1.57L14.6 8H21a2 2 0 0 1 2 2v2.104a2 2 0 0 1-.15.762l-3.095 7.515a1 1 0 0 1-.925.619H8a1 1 0 0 1-1-1V8.414a1 1 0 0 1 .293-.707z' fill='rgba(92, 128, 1, 1)'/%3E%3C/svg%3E");
|
||||
$form-feedback-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M22 15h-3V3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zm-5.293 1.293l-6.4 6.4a.5.5 0 0 1-.654.047L8.8 22.1a1.5 1.5 0 0 1-.553-1.57L9.4 16H3a2 2 0 0 1-2-2v-2.104a2 2 0 0 1 .15-.762L4.246 3.62A1 1 0 0 1 5.17 3H16a1 1 0 0 1 1 1v11.586a1 1 0 0 1-.293.707z' fill='rgba(192,50,33,1)'/%3E%3C/svg%3E");
|
||||
$line-height-base: 1.75;
|
||||
$input-placeholder-color: #6c757d;
|
||||
$input-btn-padding-y: .42rem;
|
||||
$input-btn-padding-x: .84rem;
|
||||
$btn-padding-y: .42rem;
|
||||
|
@ -33,6 +46,7 @@ $close-text-shadow: none;
|
|||
$close-color: inherit;
|
||||
$alert-border-radius: #{33% 2%} / #{11% 74%};
|
||||
$link-color: #007cbe;
|
||||
$link-decoration: none;
|
||||
$font-size-base: .9rem;
|
||||
$enable-responsive-font-sizes: true;
|
||||
$link-hover-decoration: none;
|
||||
|
@ -42,6 +56,8 @@ $dropdown-link-hover-bg: transparent;
|
|||
$dropdown-link-active-bg: transparent;
|
||||
$dropdown-link-color: rgba(0, 0, 0, 0.7);
|
||||
$dropdown-link-hover-color: rgba(0, 0, 0, 0.9);
|
||||
$dropdown-item-padding-x: 1.5rem;
|
||||
$modal-inner-padding: 2rem;
|
||||
$container-max-widths: (
|
||||
sm: 540px,
|
||||
md: 720px,
|
||||
|
@ -51,9 +67,20 @@ $nav-link-padding-y: .1rem;
|
|||
$nav-tabs-link-active-bg: #fff;
|
||||
$nav-tabs-link-hover-border-color: transparent;
|
||||
$nav-tabs-link-active-border-color: #ced4da #ced4da $nav-tabs-link-active-bg;
|
||||
$form-check-input-checked-color: var(--bs-primary);
|
||||
$form-check-input-checked-bg-color: var(--bs-primary);
|
||||
$popover-bg: var(--theme-body);
|
||||
$form-check-input-checked-color: #000;
|
||||
$tooltip-bg: #5c8001;
|
||||
$form-select-indicator-color: #808080;
|
||||
$form-select-indicator: url("data:image/svg+xml, %3Csvg fill='#{$form-select-indicator-color}' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 15.0006L7.75732 10.758L9.17154 9.34375L12 12.1722L14.8284 9.34375L16.2426 10.758L12 15.0006Z'%3E%3C/path%3E%3C/svg%3E%0A");
|
||||
$form-select-bg-position: right .25rem center;
|
||||
$form-select-bg-size: 1.5rem;
|
||||
$popover-body-padding-y: .5rem;
|
||||
$popover-max-width: 320px !default;
|
||||
$popover-border-color: var(--theme-borderColor);
|
||||
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
@import '../node_modules/bootstrap/scss/bootstrap.scss';
|
||||
|
||||
@media screen and (min-width: 899px) {
|
||||
|
||||
|
@ -135,8 +162,8 @@ mark {
|
|||
width: 100% !important;
|
||||
}
|
||||
|
||||
.custom-checkbox.custom-control-inline {
|
||||
margin-right: .5rem;
|
||||
.btn-twitter, .btn-twitter:hover, .btn-twitter:active {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
|
@ -178,7 +205,7 @@ a:hover {
|
|||
border-bottom-color: var(--theme-inputBg);
|
||||
}
|
||||
|
||||
select.custom-select,
|
||||
select,
|
||||
div[contenteditable],
|
||||
.form-control {
|
||||
background-color: var(--theme-inputBg);
|
||||
|
@ -186,26 +213,38 @@ div[contenteditable],
|
|||
border-color: var(--theme-borderColor);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
select.custom-select {
|
||||
|
||||
select.form-select {
|
||||
background-color: var(--theme-clickToContextColor);
|
||||
color: var(--theme-dropdownItemColor);
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
background-image: url("data:image/svg+xml, %3Csvg fill='%23808080' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 15.0006L7.75732 10.758L9.17154 9.34375L12 12.1722L14.8284 9.34375L16.2426 10.758L12 15.0006Z'%3E%3C/path%3E%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right .25rem center;
|
||||
background-size: 1.5rem;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: calc(1.5em + 0.5rem + 2px);
|
||||
padding: 0.25rem 1.84rem 0.25rem 0.5rem;
|
||||
font-size: .7875rem;
|
||||
vertical-align: middle;
|
||||
border-radius: 0.4rem;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
select.custom-select option {
|
||||
select option {
|
||||
// fix dropdown items not visible in darkmode on some browsers
|
||||
color: initial;
|
||||
}
|
||||
|
||||
select.custom-select:focus {
|
||||
select:focus {
|
||||
border-color: none !important;
|
||||
box-shadow: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,6 +261,7 @@ div[contenteditable]:disabled,
|
|||
.form-control[readonly] {
|
||||
background-color: var(--theme-inputDisabledBg);
|
||||
border-color: var(--theme-borderColor);
|
||||
color: var(--theme-color);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
@ -296,7 +336,7 @@ div[contenteditable]:disabled,
|
|||
|
||||
.dropdown-item.active {
|
||||
color: var(--theme-brandColor) !important;
|
||||
text-shadow: 0 0 10px var(--primary);
|
||||
text-shadow: 0 0 10px var(--bs-primary);
|
||||
}
|
||||
|
||||
.dropdown-divider {
|
||||
|
@ -358,6 +398,12 @@ footer {
|
|||
}
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
background-color: var(--theme-clickToContextColor);
|
||||
border-color: var(--theme-borderColor);
|
||||
color: var(--theme-color);
|
||||
}
|
||||
|
||||
textarea.form-control,
|
||||
div[contenteditable] {
|
||||
line-height: 1rem;
|
||||
|
@ -444,12 +490,12 @@ div[contenteditable] {
|
|||
|
||||
|
||||
.dropdown-item.active {
|
||||
text-shadow: 0 0 10px var(--primary);
|
||||
text-shadow: 0 0 10px var(--bs-primary);
|
||||
}
|
||||
|
||||
div[contenteditable]:focus,
|
||||
.form-control:focus {
|
||||
border-color: var(--primary);
|
||||
border-color: var(--bs-primary);
|
||||
}
|
||||
|
||||
.btn-secondary,
|
||||
|
@ -491,11 +537,11 @@ div[contenteditable]:focus,
|
|||
}
|
||||
|
||||
.fill-secondary {
|
||||
fill: var(--secondary);
|
||||
fill: var(--bs-secondary);
|
||||
}
|
||||
|
||||
.fill-boost {
|
||||
fill: var(--boost);
|
||||
fill: var(--bs-boost);
|
||||
}
|
||||
|
||||
.fill-white {
|
||||
|
@ -503,15 +549,15 @@ div[contenteditable]:focus,
|
|||
}
|
||||
|
||||
.fill-success {
|
||||
fill: var(--success);
|
||||
fill: var(--bs-success);
|
||||
}
|
||||
|
||||
.fill-info {
|
||||
fill: var(--info);
|
||||
fill: var(--bs-info);
|
||||
}
|
||||
|
||||
.fill-danger {
|
||||
fill: var(--danger);
|
||||
fill: var(--bs-danger);
|
||||
}
|
||||
|
||||
.fill-theme-color {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
align-items: center;
|
||||
margin-right: -15px;
|
||||
padding-right: 15px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.detail {
|
||||
|
@ -31,6 +32,10 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.sats.head {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.head {
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
|
|
Loading…
Reference in New Issue