Add more components, message actions & reactions (#339)
* hide sidebar on small screen * add reply component * add radix dependencies * add dropdown menu component * add popover component * add tooltip component * add react button component * add reaction popover * update chat message actions * add basic dialog and sheet components * add ref to Button component * add chat message reactions * add reply and reactions to chat message * remove console.log * add dropdown menu to topbar * add ref and support aria in IconButton * yarn.lock * add stylesheet reset to storybook * add pinned state to message * remove extraneous component * add all button variants * fix button icons * use IconButton in actions * remove erroneous character * add reply to composer + simplify * use correct button in reply
This commit is contained in:
parent
a5fdd22d51
commit
84ec492292
|
@ -88,12 +88,9 @@ function App() {
|
||||||
<Messages />
|
<Messages />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Composer
|
<div id="composer">
|
||||||
backgroundColor="$blurBackground"
|
<Composer isBlurred={shouldBlurBottom} reply={false} />
|
||||||
paddingBottom={56}
|
</div>
|
||||||
isBlurred={shouldBlurBottom}
|
|
||||||
style={{ marginTop: -112 }}
|
|
||||||
/>
|
|
||||||
</main>
|
</main>
|
||||||
<AnimatePresence enterVariant="fromRight" exitVariant="fromLeft">
|
<AnimatePresence enterVariant="fromRight" exitVariant="fromLeft">
|
||||||
{showMembers && (
|
{showMembers && (
|
||||||
|
|
|
@ -17,6 +17,7 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 56px 1fr 100px;
|
grid-template-rows: 56px 1fr 100px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
@ -45,7 +46,24 @@ body,
|
||||||
margin-top: -56px;
|
margin-top: -56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#composer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#members {
|
#members {
|
||||||
width: 352px;
|
width: 352px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
#app {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { TamaguiProvider } from '@tamagui/core'
|
||||||
import { config } from '../src'
|
import { config } from '../src'
|
||||||
import { Parameters, Decorator } from '@storybook/react'
|
import { Parameters, Decorator } from '@storybook/react'
|
||||||
|
|
||||||
|
import './reset.css'
|
||||||
|
|
||||||
export const parameters: Parameters = {
|
export const parameters: Parameters = {
|
||||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||||
controls: {
|
controls: {
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
1. Use a more-intuitive box-sizing model.
|
||||||
|
*/
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2. Remove default margin
|
||||||
|
*/
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
3. Allow percentage-based heights in the application
|
||||||
|
*/
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
overflow: hidden;
|
||||||
|
overscroll-behavior-y: none; /* not working on Safari */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Typographic tweaks!
|
||||||
|
4. Add accessible line-height
|
||||||
|
5. Improve text rendering
|
||||||
|
*/
|
||||||
|
body {
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
6. Improve media defaults
|
||||||
|
*/
|
||||||
|
img,
|
||||||
|
picture,
|
||||||
|
video,
|
||||||
|
canvas,
|
||||||
|
svg {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
7. Remove built-in form typography styles
|
||||||
|
*/
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
8. Avoid text overflows
|
||||||
|
*/
|
||||||
|
p,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
9. Create a root stacking context
|
||||||
|
*/
|
||||||
|
#root,
|
||||||
|
#__next {
|
||||||
|
isolation: isolate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
10. Remove user selection on buttons
|
||||||
|
*/
|
||||||
|
button {
|
||||||
|
user-select: none;
|
||||||
|
}
|
|
@ -22,6 +22,9 @@
|
||||||
"react-native-web": "^0.18.0"
|
"react-native-web": "^0.18.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||||
|
"@radix-ui/react-popover": "^1.0.3",
|
||||||
|
"@radix-ui/react-tooltip": "^1.0.3",
|
||||||
"@status-im/icons": "*",
|
"@status-im/icons": "*",
|
||||||
"@tamagui/animations-css": "1.0.15",
|
"@tamagui/animations-css": "1.0.15",
|
||||||
"@tamagui/animations-react-native": "1.0.15",
|
"@tamagui/animations-react-native": "1.0.15",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { action } from '@storybook/addon-actions'
|
||||||
|
import { Stack } from 'tamagui'
|
||||||
|
|
||||||
import { Button } from './button'
|
import { Button } from './button'
|
||||||
|
|
||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
@ -5,18 +8,25 @@ import type { Meta, StoryObj } from '@storybook/react'
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
const meta: Meta<typeof Button> = {
|
const meta: Meta<typeof Button> = {
|
||||||
component: Button,
|
component: Button,
|
||||||
argTypes: {},
|
args: {
|
||||||
|
onPress: action('press'),
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
disabled: {
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [
|
||||||
|
Story => (
|
||||||
|
<Stack alignItems="flex-start">
|
||||||
|
<Story />
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
type Story = StoryObj<typeof Button>
|
type Story = StoryObj<typeof Button>
|
||||||
|
|
||||||
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
|
||||||
export const Primary: Story = {
|
|
||||||
args: {
|
|
||||||
children: 'Click me',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const icon = (
|
const icon = (
|
||||||
<svg
|
<svg
|
||||||
width="20"
|
width="20"
|
||||||
|
@ -34,14 +44,43 @@ const icon = (
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Primary: Story = {
|
||||||
|
args: {
|
||||||
|
children: 'Click me',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrimaryDisabled: Story = {
|
||||||
|
args: {
|
||||||
|
children: 'Click me',
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrimaryFullWidth: Story = {
|
||||||
|
args: {
|
||||||
|
children: 'Click me',
|
||||||
|
width: 'full',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const Primary32: Story = {
|
export const Primary32: Story = {
|
||||||
name: 'Primary/32px',
|
name: 'Primary / 32',
|
||||||
args: {
|
args: {
|
||||||
size: 32,
|
size: 32,
|
||||||
children: 'Click me',
|
children: 'Click me',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Primary24: Story = {
|
||||||
|
name: 'Primary / 24',
|
||||||
|
args: {
|
||||||
|
size: 24,
|
||||||
|
children: 'Click me',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const PrimaryIconBefore: Story = {
|
export const PrimaryIconBefore: Story = {
|
||||||
name: 'Primary icon before',
|
name: 'Primary icon before',
|
||||||
args: {
|
args: {
|
||||||
|
@ -85,4 +124,11 @@ export const Ghost: Story = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Danger: Story = {
|
||||||
|
args: {
|
||||||
|
type: 'danger',
|
||||||
|
children: 'Click me',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export default meta
|
export default meta
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
|
import { forwardRef } from 'react'
|
||||||
|
|
||||||
import { Stack, styled } from '@tamagui/core'
|
import { Stack, styled } from '@tamagui/core'
|
||||||
|
|
||||||
import { Paragraph } from '../typography'
|
import { Paragraph } from '../typography'
|
||||||
|
|
||||||
import type { GetProps } from '@tamagui/core'
|
import type { GetProps } from '@tamagui/core'
|
||||||
// import { Pressable } from 'react-native'
|
import type { Ref } from 'react'
|
||||||
|
|
||||||
const Base = styled(Stack, {
|
const Base = styled(Stack, {
|
||||||
name: 'Button',
|
name: 'Button',
|
||||||
accessibilityRole: 'button',
|
accessibilityRole: 'button',
|
||||||
|
|
||||||
borderRadius: 12,
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingTop: 7,
|
paddingTop: 7,
|
||||||
paddingBottom: 9,
|
paddingBottom: 9,
|
||||||
cursor: 'pointer',
|
|
||||||
|
|
||||||
alignItems: 'center',
|
cursor: 'pointer',
|
||||||
animation: 'fast',
|
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
|
animation: 'fast',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: 'transparent',
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
type: {
|
type: {
|
||||||
|
@ -28,9 +33,19 @@ const Base = styled(Stack, {
|
||||||
pressStyle: { backgroundColor: '$primaryHover' },
|
pressStyle: { backgroundColor: '$primaryHover' },
|
||||||
},
|
},
|
||||||
positive: {
|
positive: {
|
||||||
backgroundColor: '$success',
|
backgroundColor: '$success-50',
|
||||||
hoverStyle: { backgroundColor: '$successHover' },
|
hoverStyle: { backgroundColor: '$success-60' },
|
||||||
pressStyle: { backgroundColor: '$successHover' },
|
pressStyle: { backgroundColor: '$success-50' },
|
||||||
|
},
|
||||||
|
grey: {
|
||||||
|
backgroundColor: '$neutral-10',
|
||||||
|
hoverStyle: { backgroundColor: '$neutral-20' },
|
||||||
|
pressStyle: { backgroundColor: '$neutral-30' },
|
||||||
|
},
|
||||||
|
darkGrey: {
|
||||||
|
backgroundColor: '$neutral-20',
|
||||||
|
hoverStyle: { backgroundColor: '$neutral-30' },
|
||||||
|
pressStyle: { backgroundColor: '$neutral-40' },
|
||||||
},
|
},
|
||||||
outline: {
|
outline: {
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
@ -43,23 +58,47 @@ const Base = styled(Stack, {
|
||||||
hoverStyle: { backgroundColor: '$neutral-10' },
|
hoverStyle: { backgroundColor: '$neutral-10' },
|
||||||
pressStyle: { backgroundColor: '$neutral-20' },
|
pressStyle: { backgroundColor: '$neutral-20' },
|
||||||
},
|
},
|
||||||
|
danger: {
|
||||||
|
backgroundColor: '$danger',
|
||||||
|
hoverStyle: { backgroundColor: '$danger-60' },
|
||||||
|
pressStyle: { backgroundColor: '$danger' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
disabled: {
|
||||||
|
true: {
|
||||||
|
opacity: 0.3,
|
||||||
|
cursor: 'default',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
size: {
|
size: {
|
||||||
40: {
|
40: {
|
||||||
|
minHeight: 40,
|
||||||
|
borderRadius: 12,
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingTop: 7,
|
paddingTop: 7,
|
||||||
paddingBottom: 9,
|
paddingBottom: 9,
|
||||||
},
|
},
|
||||||
32: {
|
32: {
|
||||||
|
minHeight: 32,
|
||||||
|
borderRadius: 10,
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingTop: 4,
|
paddingTop: 4,
|
||||||
paddingBottom: 6,
|
paddingBottom: 6,
|
||||||
},
|
},
|
||||||
|
24: {
|
||||||
|
minHeight: 24,
|
||||||
|
borderRadius: 8,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 4,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
iconOnly: {
|
iconOnly: {
|
||||||
true: {
|
true: {
|
||||||
|
space: 0,
|
||||||
paddingHorizontal: 8,
|
paddingHorizontal: 8,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -67,11 +106,10 @@ const Base = styled(Stack, {
|
||||||
})
|
})
|
||||||
|
|
||||||
const ButtonText = styled(Paragraph, {
|
const ButtonText = styled(Paragraph, {
|
||||||
textAlign: 'center',
|
|
||||||
weight: 'medium',
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
space: 4,
|
space: 4,
|
||||||
|
weight: 'medium',
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
type: {
|
type: {
|
||||||
|
@ -81,12 +119,33 @@ const ButtonText = styled(Paragraph, {
|
||||||
positive: {
|
positive: {
|
||||||
color: '$white-100',
|
color: '$white-100',
|
||||||
},
|
},
|
||||||
|
grey: {
|
||||||
|
color: '$neutral-100',
|
||||||
|
},
|
||||||
|
darkGrey: {
|
||||||
|
color: '$neutral-100',
|
||||||
|
},
|
||||||
outline: {
|
outline: {
|
||||||
color: '$neutral-100',
|
color: '$neutral-100',
|
||||||
},
|
},
|
||||||
ghost: {
|
ghost: {
|
||||||
color: '$neutral-100',
|
color: '$neutral-100',
|
||||||
},
|
},
|
||||||
|
danger: {
|
||||||
|
color: '$white-100',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
size: {
|
||||||
|
40: {
|
||||||
|
variant: 'normal',
|
||||||
|
},
|
||||||
|
32: {
|
||||||
|
variant: 'normal',
|
||||||
|
},
|
||||||
|
24: {
|
||||||
|
variant: 'smaller',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as const,
|
} as const,
|
||||||
})
|
})
|
||||||
|
@ -95,19 +154,18 @@ type BaseProps = GetProps<typeof Base>
|
||||||
|
|
||||||
type Props = BaseProps & {
|
type Props = BaseProps & {
|
||||||
children?: string
|
children?: string
|
||||||
icon?: React.ReactNode
|
|
||||||
type?: BaseProps['type']
|
type?: BaseProps['type']
|
||||||
size?: BaseProps['size']
|
size?: BaseProps['size']
|
||||||
|
disabled?: boolean
|
||||||
|
icon?: React.ReactNode
|
||||||
iconAfter?: React.ReactNode
|
iconAfter?: React.ReactNode
|
||||||
onPress?: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button = (props: Props) => {
|
const Button = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||||
const {
|
const {
|
||||||
type = 'primary',
|
type = 'primary',
|
||||||
size = 40,
|
size = 40,
|
||||||
children,
|
children,
|
||||||
onPress,
|
|
||||||
icon,
|
icon,
|
||||||
iconAfter,
|
iconAfter,
|
||||||
...rest
|
...rest
|
||||||
|
@ -116,14 +174,8 @@ const Button = (props: Props) => {
|
||||||
const iconOnly = !children && Boolean(icon)
|
const iconOnly = !children && Boolean(icon)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Base
|
<Base {...rest} ref={ref} type={type} size={size} iconOnly={iconOnly}>
|
||||||
{...rest}
|
<ButtonText type={type} size={size}>
|
||||||
type={type}
|
|
||||||
size={size}
|
|
||||||
iconOnly={iconOnly}
|
|
||||||
onPress={onPress}
|
|
||||||
>
|
|
||||||
<ButtonText type={type}>
|
|
||||||
{icon}
|
{icon}
|
||||||
{children}
|
{children}
|
||||||
{iconAfter}
|
{iconAfter}
|
||||||
|
@ -132,5 +184,7 @@ const Button = (props: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Button }
|
const _Button = forwardRef(Button)
|
||||||
|
|
||||||
|
export { _Button as Button }
|
||||||
export type { Props as ButtonProps }
|
export type { Props as ButtonProps }
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { Button } from './button'
|
export { type ButtonProps, Button } from './button'
|
||||||
|
|
|
@ -11,30 +11,19 @@ import { Stack, XStack, YStack } from 'tamagui'
|
||||||
|
|
||||||
import { IconButton } from '../icon-button'
|
import { IconButton } from '../icon-button'
|
||||||
import { Input } from '../input'
|
import { Input } from '../input'
|
||||||
|
import { Reply } from '../reply'
|
||||||
|
|
||||||
import type { GetProps } from '@tamagui/core'
|
interface Props {
|
||||||
import type { ViewProps } from 'react-native'
|
isBlurred: boolean
|
||||||
|
reply: boolean
|
||||||
|
}
|
||||||
|
|
||||||
type BaseProps = GetProps<typeof YStack>
|
const Composer = (props: Props) => {
|
||||||
|
const { isBlurred, reply } = props
|
||||||
const Composer = (
|
|
||||||
props: Omit<BaseProps, 'style'> & {
|
|
||||||
placeholderTextColor?: BaseProps['backgroundColor']
|
|
||||||
iconOptionsColor?: BaseProps['backgroundColor']
|
|
||||||
isBlurred?: boolean
|
|
||||||
style?: ViewProps['style']
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
const { backgroundColor, isBlurred, style: styleFromProps, ...rest } = props
|
|
||||||
const style = styleFromProps ? Object.assign(styleFromProps) : {}
|
|
||||||
|
|
||||||
const [isFocused, setIsFocused] = useState(false)
|
const [isFocused, setIsFocused] = useState(false)
|
||||||
|
|
||||||
const applyVariantStyles:
|
const iconButtonBlurred = isBlurred && !isFocused
|
||||||
| {
|
|
||||||
blurred: boolean
|
|
||||||
}
|
|
||||||
| undefined = isBlurred && !isFocused ? { blurred: true } : undefined
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BlurView
|
<BlurView
|
||||||
|
@ -42,25 +31,35 @@ const Composer = (
|
||||||
style={{
|
style={{
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
...style,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<YStack
|
<YStack
|
||||||
animation="fast"
|
animation="fast"
|
||||||
backgroundColor={isFocused ? '$background' : backgroundColor}
|
backgroundColor={isFocused ? '$background' : '$blurBackground'}
|
||||||
shadowColor={!isBlurred || isFocused ? 'rgba(9, 16, 28, 0.08)' : 'none'}
|
shadowColor={!isBlurred || isFocused ? 'rgba(9, 16, 28, 0.08)' : 'none'}
|
||||||
shadowOffset={{ width: 4, height: !isBlurred || isFocused ? 4 : 0 }}
|
shadowOffset={{ width: 4, height: !isBlurred || isFocused ? 4 : 0 }}
|
||||||
shadowRadius={20}
|
shadowRadius={20}
|
||||||
borderTopLeftRadius={20}
|
borderTopLeftRadius={20}
|
||||||
borderTopRightRadius={20}
|
borderTopRightRadius={20}
|
||||||
px={16}
|
px={16}
|
||||||
pt={8}
|
py={12}
|
||||||
width="100%"
|
|
||||||
style={{
|
style={{
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
}}
|
}}
|
||||||
{...rest}
|
|
||||||
>
|
>
|
||||||
|
{reply && (
|
||||||
|
<Stack paddingLeft={4} paddingBottom={4}>
|
||||||
|
<Reply
|
||||||
|
type="text"
|
||||||
|
name="Alisher"
|
||||||
|
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
||||||
|
onClose={() => {
|
||||||
|
console.log('close')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
className="composer-input"
|
className="composer-input"
|
||||||
placeholder="Type something..."
|
placeholder="Type something..."
|
||||||
|
@ -70,35 +69,35 @@ const Composer = (
|
||||||
onBlur={() => setIsFocused(false)}
|
onBlur={() => setIsFocused(false)}
|
||||||
onFocus={() => setIsFocused(true)}
|
onFocus={() => setIsFocused(true)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<XStack
|
<XStack
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
pt={8}
|
paddingTop={12}
|
||||||
backgroundColor="transparent"
|
backgroundColor="transparent"
|
||||||
>
|
>
|
||||||
<Stack space={12} flexDirection="row" backgroundColor="transparent">
|
<Stack space={12} flexDirection="row" backgroundColor="transparent">
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
icon={<ImageIcon />}
|
icon={<ImageIcon />}
|
||||||
{...applyVariantStyles}
|
blurred={iconButtonBlurred}
|
||||||
selected
|
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
icon={<ReactionIcon />}
|
icon={<ReactionIcon />}
|
||||||
{...applyVariantStyles}
|
blurred={iconButtonBlurred}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
icon={<FormatIcon />}
|
icon={<FormatIcon />}
|
||||||
disabled
|
disabled
|
||||||
{...applyVariantStyles}
|
blurred={iconButtonBlurred}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="outline"
|
variant="outline"
|
||||||
icon={<AudioIcon />}
|
icon={<AudioIcon />}
|
||||||
{...applyVariantStyles}
|
blurred={iconButtonBlurred}
|
||||||
/>
|
/>
|
||||||
</XStack>
|
</XStack>
|
||||||
</YStack>
|
</YStack>
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { Dialog } from './dialog'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
|
const meta: Meta<typeof Dialog> = {
|
||||||
|
title: 'Web/Dialog',
|
||||||
|
// component: Sheet,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Web?node-id=611%3A36006&t=Gyy71OAckl3b2TWj-4',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Dialog>
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {},
|
||||||
|
render: () => (
|
||||||
|
<Dialog>
|
||||||
|
<Button>Trigger</Button>
|
||||||
|
<Dialog.Content>test</Dialog.Content>
|
||||||
|
</Dialog>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { forwardRef } from 'react'
|
||||||
|
|
||||||
|
import { Content, Overlay, Portal, Root, Trigger } from '@radix-ui/react-dialog'
|
||||||
|
import { useMedia } from 'tamagui'
|
||||||
|
|
||||||
|
import { Sheet } from '../sheet'
|
||||||
|
|
||||||
|
import type { Ref } from 'react'
|
||||||
|
import type React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: [React.ReactElement, React.ReactElement]
|
||||||
|
open?: boolean
|
||||||
|
onOpenChange?: (open: boolean) => void
|
||||||
|
press?: 'normal' | 'long'
|
||||||
|
}
|
||||||
|
|
||||||
|
// const DialogTrigger = (
|
||||||
|
// props: DialogTriggerProps & {
|
||||||
|
// press: Props['press']
|
||||||
|
// children: React.ReactElement
|
||||||
|
// }
|
||||||
|
// ) => {
|
||||||
|
// const { children, press, onClick, type, ...triggerProps } = props
|
||||||
|
// const handler = press === 'normal' ? 'onPress' : 'onLongPress'
|
||||||
|
|
||||||
|
// // console.log('dialog', press, onClick, { ...triggerProps, [handler]: onClick })
|
||||||
|
// return cloneElement(children, { ref, ...triggerProps, [handler]: onClick })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: allow customization of press duration
|
||||||
|
const Dialog = (props: Props) => {
|
||||||
|
const { children, open, onOpenChange /* press = 'normal' */ } = props
|
||||||
|
|
||||||
|
const [trigger, content] = children
|
||||||
|
|
||||||
|
const media = useMedia()
|
||||||
|
|
||||||
|
if (media.sm) {
|
||||||
|
return (
|
||||||
|
<Sheet>
|
||||||
|
{trigger}
|
||||||
|
{content}
|
||||||
|
</Sheet>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Root open={open} onOpenChange={onOpenChange}>
|
||||||
|
{/* TRIGGER */}
|
||||||
|
<Trigger asChild>{trigger}</Trigger>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<Portal>
|
||||||
|
<Overlay
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
inset: 0,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{content}
|
||||||
|
</Portal>
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DialogContentProps {
|
||||||
|
// title: string
|
||||||
|
// description?: string
|
||||||
|
children: React.ReactNode
|
||||||
|
// action: string
|
||||||
|
// onAction: (close: VoidFunction) => void
|
||||||
|
// onCancel?: () => void
|
||||||
|
initialFocusRef?: React.RefObject<HTMLElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
const DialogContent = (props: DialogContentProps, ref: Ref<HTMLDivElement>) => {
|
||||||
|
const { children, initialFocusRef } = props
|
||||||
|
|
||||||
|
const handleOpenAutoFocus = (event: Event) => {
|
||||||
|
if (initialFocusRef?.current) {
|
||||||
|
event.preventDefault()
|
||||||
|
initialFocusRef.current.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const media = useMedia()
|
||||||
|
|
||||||
|
if (media.sm) {
|
||||||
|
return <Sheet.Content>{children}</Sheet.Content>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Content
|
||||||
|
ref={ref}
|
||||||
|
onOpenAutoFocus={handleOpenAutoFocus}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
padding: 8,
|
||||||
|
width: 400,
|
||||||
|
borderRadius: 8,
|
||||||
|
position: 'fixed',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Content>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog.Content = forwardRef(DialogContent)
|
||||||
|
|
||||||
|
export { Dialog }
|
|
@ -0,0 +1 @@
|
||||||
|
export { Dialog } from './dialog'
|
|
@ -0,0 +1,85 @@
|
||||||
|
import {
|
||||||
|
CopyIcon,
|
||||||
|
DeleteIcon,
|
||||||
|
EditIcon,
|
||||||
|
ForwardIcon,
|
||||||
|
LinkIcon,
|
||||||
|
PinIcon,
|
||||||
|
ReplyIcon,
|
||||||
|
} from '@status-im/icons/20'
|
||||||
|
import { action } from '@storybook/addon-actions'
|
||||||
|
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { DropdownMenu } from './dropdown-menu'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
const meta: Meta<typeof DropdownMenu> = {
|
||||||
|
title: 'Web/dropdown menu',
|
||||||
|
component: DropdownMenu,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Web?node-id=1931%3A31188&t=rOKELbVkzya48FJE-0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof DropdownMenu>
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {},
|
||||||
|
|
||||||
|
render: args => {
|
||||||
|
return (
|
||||||
|
<DropdownMenu {...args}>
|
||||||
|
<Button>Open</Button>
|
||||||
|
|
||||||
|
<DropdownMenu.Content sideOffset={10}>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<EditIcon />}
|
||||||
|
label="Edit message"
|
||||||
|
onSelect={action('edit')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<ReplyIcon />}
|
||||||
|
label="Reply"
|
||||||
|
onSelect={action('reply')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<CopyIcon />}
|
||||||
|
label="Copy text"
|
||||||
|
onSelect={action('copy')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<PinIcon />}
|
||||||
|
label="Pin to the channel"
|
||||||
|
onSelect={action('pin')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<ForwardIcon />}
|
||||||
|
label="Forward"
|
||||||
|
onSelect={action('forward')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<LinkIcon />}
|
||||||
|
label="Share link to message"
|
||||||
|
onSelect={action('share')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
label="Delete message"
|
||||||
|
danger
|
||||||
|
onSelect={action('delete')}
|
||||||
|
/>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,108 @@
|
||||||
|
import { cloneElement } from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem as RadixDropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
// Label,
|
||||||
|
Portal,
|
||||||
|
Root,
|
||||||
|
Trigger,
|
||||||
|
} from '@radix-ui/react-dropdown-menu'
|
||||||
|
import { Stack, styled } from 'tamagui'
|
||||||
|
|
||||||
|
import { Paragraph } from '../typography'
|
||||||
|
|
||||||
|
const Content = styled(DropdownMenuContent, {
|
||||||
|
name: 'DropdownMenuContent',
|
||||||
|
acceptsClassName: true,
|
||||||
|
|
||||||
|
width: 352,
|
||||||
|
padding: 8,
|
||||||
|
borderRadius: 16,
|
||||||
|
backgroundColor: '$white-100',
|
||||||
|
|
||||||
|
shadowRadius: 30,
|
||||||
|
shadowOffset: '0px 8px',
|
||||||
|
shadowColor: 'rgba(9, 16, 28, 0.12)',
|
||||||
|
})
|
||||||
|
|
||||||
|
const Item = styled(RadixDropdownMenuItem, {
|
||||||
|
name: 'DropdownMenuItem',
|
||||||
|
acceptsClassName: true,
|
||||||
|
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 8,
|
||||||
|
borderRadius: 12,
|
||||||
|
cursor: 'pointer',
|
||||||
|
userSelect: 'none',
|
||||||
|
|
||||||
|
hoverStyle: {
|
||||||
|
backgroundColor: '$neutral-5',
|
||||||
|
},
|
||||||
|
|
||||||
|
pressStyle: {
|
||||||
|
backgroundColor: '$neutral-10',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const Separator = styled(DropdownMenuSeparator, {
|
||||||
|
name: 'DropdownMenuSeparator',
|
||||||
|
acceptsClassName: true,
|
||||||
|
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: '$neutral-10',
|
||||||
|
marginVertical: 8,
|
||||||
|
marginLeft: -8,
|
||||||
|
marginRight: -8,
|
||||||
|
})
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: [React.ReactElement, React.ReactElement]
|
||||||
|
modal?: false
|
||||||
|
onOpenChange?: (open: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const DropdownMenu = (props: Props) => {
|
||||||
|
const { children, onOpenChange, modal } = props
|
||||||
|
|
||||||
|
const [trigger, content] = children
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Root onOpenChange={onOpenChange} modal={modal}>
|
||||||
|
<Trigger asChild>{trigger}</Trigger>
|
||||||
|
<Portal>{content}</Portal>
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DropdownMenuItemProps {
|
||||||
|
icon: React.ReactElement
|
||||||
|
label: string
|
||||||
|
onSelect: () => void
|
||||||
|
danger?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const DropdownMenuItem = (props: DropdownMenuItemProps) => {
|
||||||
|
const { icon, label, onSelect, danger } = props
|
||||||
|
|
||||||
|
const iconColor = danger ? '$danger-50' : '$neutral-50'
|
||||||
|
const textColor = danger ? '$danger-50' : '$neutral-100'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Item onSelect={onSelect}>
|
||||||
|
<Stack marginRight={12}>{cloneElement(icon, { color: iconColor })}</Stack>
|
||||||
|
<Paragraph weight="medium" color={textColor}>
|
||||||
|
{label}
|
||||||
|
</Paragraph>
|
||||||
|
</Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu.Content = Content
|
||||||
|
DropdownMenu.Item = DropdownMenuItem
|
||||||
|
DropdownMenu.Separator = Separator
|
||||||
|
|
||||||
|
export { DropdownMenu }
|
||||||
|
export type { Props as DropdownMenuProps }
|
|
@ -0,0 +1 @@
|
||||||
|
export { DropdownMenu } from './dropdown-menu'
|
|
@ -1,8 +1,8 @@
|
||||||
import { cloneElement } from 'react'
|
import { cloneElement, forwardRef } from 'react'
|
||||||
|
|
||||||
import { Stack, styled } from '@tamagui/core'
|
import { Stack, styled } from '@tamagui/core'
|
||||||
|
|
||||||
import type React from 'react'
|
import type { Ref } from 'react'
|
||||||
|
|
||||||
const Base = styled(Stack, {
|
const Base = styled(Stack, {
|
||||||
name: 'IconButton',
|
name: 'IconButton',
|
||||||
|
@ -108,6 +108,9 @@ interface Props {
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
// FIXME: enforce aria-label for accessibility
|
// FIXME: enforce aria-label for accessibility
|
||||||
// 'aria-label'?: string
|
// 'aria-label'?: string
|
||||||
|
// FIXME: update to latest RN
|
||||||
|
'aria-expanded'?: boolean
|
||||||
|
'aria-selected'?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconColor = {
|
const iconColor = {
|
||||||
|
@ -165,26 +168,22 @@ const getSelectedVariant = ({
|
||||||
return variant
|
return variant
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconButton = (props: Props) => {
|
const IconButton = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||||
const {
|
const { icon, blurred, variant = 'default', ...rest } = props
|
||||||
icon,
|
|
||||||
selected,
|
const selected =
|
||||||
blurred,
|
props.selected || props['aria-expanded'] || props['aria-selected']
|
||||||
onPress,
|
|
||||||
variant = 'default',
|
|
||||||
disabled,
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const state = getStateForIconColor({ blurred, selected })
|
const state = getStateForIconColor({ blurred, selected })
|
||||||
const selectedVariant = getSelectedVariant({ selected, variant, blurred })
|
const selectedVariant = getSelectedVariant({ selected, variant, blurred })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Base
|
<Base
|
||||||
|
{...rest}
|
||||||
|
ref={ref}
|
||||||
variant={variant}
|
variant={variant}
|
||||||
selected={selectedVariant}
|
selected={selectedVariant}
|
||||||
onPress={onPress}
|
|
||||||
blurred={blurred ? variant : undefined}
|
blurred={blurred ? variant : undefined}
|
||||||
disabled={disabled}
|
|
||||||
>
|
>
|
||||||
{cloneElement(icon, {
|
{cloneElement(icon, {
|
||||||
color: iconColor[variant][state],
|
color: iconColor[variant][state],
|
||||||
|
@ -194,5 +193,7 @@ const IconButton = (props: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { IconButton }
|
const _IconButton = forwardRef(IconButton)
|
||||||
|
|
||||||
|
export { _IconButton as IconButton }
|
||||||
export type { Props as IconButtonProps }
|
export type { Props as IconButtonProps }
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const InputFrame = styled(
|
||||||
|
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
|
|
||||||
height: 40,
|
height: 32,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
|
|
||||||
animation: 'fast',
|
animation: 'fast',
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import { Stack, Unspaced, XStack, YStack } from 'tamagui'
|
|
||||||
|
|
||||||
import { Author } from '../author/author'
|
|
||||||
import { Avatar } from '../avatar'
|
|
||||||
import { Image } from '../image'
|
|
||||||
import { Paragraph } from '../typography'
|
|
||||||
import { Actions } from './components/actions'
|
|
||||||
import { Reactions } from './components/reactions'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
text?: React.ReactNode
|
|
||||||
images?: Array<{ url: string }>
|
|
||||||
reactions?: []
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChatMessage = (props: Props) => {
|
|
||||||
const { text, images, reactions } = props
|
|
||||||
|
|
||||||
const [hovered, setHovered] = React.useState(false)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<XStack
|
|
||||||
space={10}
|
|
||||||
position="relative"
|
|
||||||
alignItems="flex-start"
|
|
||||||
paddingHorizontal={8}
|
|
||||||
paddingVertical={12}
|
|
||||||
borderRadius={16}
|
|
||||||
hoverStyle={{
|
|
||||||
backgroundColor: '$neutral-5',
|
|
||||||
}}
|
|
||||||
onHoverIn={() => setHovered(true)}
|
|
||||||
onHoverOut={() => setHovered(false)}
|
|
||||||
>
|
|
||||||
{hovered && (
|
|
||||||
<Unspaced>
|
|
||||||
<Actions
|
|
||||||
onClick={() => {
|
|
||||||
console.log('clicked')
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Unspaced>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Avatar
|
|
||||||
size={32}
|
|
||||||
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
|
||||||
indicator="online"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<YStack flex={1}>
|
|
||||||
<Author
|
|
||||||
name="Alisher Yakupov"
|
|
||||||
address="zQ3...9d4Gs0"
|
|
||||||
status="verified"
|
|
||||||
time="09:30"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{text && (
|
|
||||||
<Paragraph flexGrow={0} weight="regular" color="$neutral-100">
|
|
||||||
{text}
|
|
||||||
</Paragraph>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{images?.map(image => (
|
|
||||||
<Stack
|
|
||||||
key={image.url}
|
|
||||||
marginTop={8}
|
|
||||||
$gtMd={{
|
|
||||||
maxWidth: 320,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Image src={image.url} width="full" height={320} radius={12} />
|
|
||||||
</Stack>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{reactions && (
|
|
||||||
<Stack marginTop={8}>
|
|
||||||
<Reactions />
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</YStack>
|
|
||||||
</XStack>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export { ChatMessage }
|
|
|
@ -1,11 +1,21 @@
|
||||||
import { Actions } from './actions'
|
import { Actions } from './actions'
|
||||||
|
|
||||||
|
import type { ReactionsType } from '../types'
|
||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
const reactions: ReactionsType = {
|
||||||
|
love: new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-up': new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-down': new Set(['me', '1', '2', '3']),
|
||||||
|
}
|
||||||
|
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
const meta: Meta<typeof Actions> = {
|
const meta: Meta<typeof Actions> = {
|
||||||
title: 'Messages/actions',
|
title: 'Messages/actions',
|
||||||
component: Actions,
|
component: Actions,
|
||||||
|
args: {
|
||||||
|
reactions,
|
||||||
|
},
|
||||||
argTypes: {},
|
argTypes: {},
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
|
|
|
@ -1,18 +1,47 @@
|
||||||
import { AddReactionIcon, OptionsIcon, ReplyIcon } from '@status-im/icons/20'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
AddReactionIcon,
|
||||||
|
CopyIcon,
|
||||||
|
DeleteIcon,
|
||||||
|
EditIcon,
|
||||||
|
ForwardIcon,
|
||||||
|
LinkIcon,
|
||||||
|
OptionsIcon,
|
||||||
|
PinIcon,
|
||||||
|
ReplyIcon,
|
||||||
|
} from '@status-im/icons/20'
|
||||||
import { Stack } from 'tamagui'
|
import { Stack } from 'tamagui'
|
||||||
|
|
||||||
import { Button } from '../../button'
|
import { DropdownMenu } from '../../dropdown-menu'
|
||||||
|
import { IconButton } from '../../icon-button'
|
||||||
|
import { ReactionPopover } from './reaction-popover'
|
||||||
|
|
||||||
|
import type { ReactionsType } from '../types'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClick: VoidFunction
|
reactions: ReactionsType
|
||||||
|
onOpenChange: (open: boolean) => void
|
||||||
|
onReplyPress: VoidFunction
|
||||||
|
// onEditPress: VoidFunction
|
||||||
|
// onDeletePress: VoidFunction
|
||||||
}
|
}
|
||||||
export const Actions = (_props: Props) => {
|
|
||||||
|
export const Actions = (props: Props) => {
|
||||||
|
const { reactions, onOpenChange, onReplyPress } = props
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => onOpenChange(false)
|
||||||
|
}, [onOpenChange])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
backgroundColor="$white-100"
|
backgroundColor="$white-100"
|
||||||
borderWidth={1}
|
borderWidth={1}
|
||||||
borderColor="$neutral-10"
|
borderColor="$neutral-10"
|
||||||
borderRadius={10}
|
borderRadius={12}
|
||||||
|
padding={2}
|
||||||
|
space={2}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top={-16}
|
top={-16}
|
||||||
|
@ -23,9 +52,82 @@ export const Actions = (_props: Props) => {
|
||||||
shadowColor="rgba(9, 16, 28, 0.08)"
|
shadowColor="rgba(9, 16, 28, 0.08)"
|
||||||
zIndex={10}
|
zIndex={10}
|
||||||
>
|
>
|
||||||
<Button type="ghost" icon={<AddReactionIcon />} borderRadius={0} />
|
{/* REACTION */}
|
||||||
<Button type="ghost" icon={<ReplyIcon />} borderRadius={0} />
|
<ReactionPopover
|
||||||
<Button type="ghost" icon={<OptionsIcon />} borderRadius={0} />
|
reactions={reactions}
|
||||||
|
side="left"
|
||||||
|
sideOffset={6}
|
||||||
|
onOpenChange={onOpenChange}
|
||||||
|
>
|
||||||
|
<IconButton variant="outline" icon={<AddReactionIcon />} />
|
||||||
|
</ReactionPopover>
|
||||||
|
|
||||||
|
{/* REPLY */}
|
||||||
|
<IconButton
|
||||||
|
variant="outline"
|
||||||
|
icon={<ReplyIcon />}
|
||||||
|
onPress={onReplyPress}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* EDIT */}
|
||||||
|
{/* <IconButton
|
||||||
|
variant="outline"
|
||||||
|
icon={<EditIcon />}
|
||||||
|
onPress={onEditPress}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
{/* DELETE */}
|
||||||
|
{/* <IconButton
|
||||||
|
variant="outline"
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
onPress={onDeletePress}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
{/* OPTIONS MENU */}
|
||||||
|
<DropdownMenu modal={false} onOpenChange={onOpenChange}>
|
||||||
|
<IconButton variant="outline" icon={<OptionsIcon />} />
|
||||||
|
<DropdownMenu.Content align="end" sideOffset={10}>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<EditIcon />}
|
||||||
|
label="Edit message"
|
||||||
|
onSelect={() => console.log('edit')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<ReplyIcon />}
|
||||||
|
label="Reply"
|
||||||
|
onSelect={() => console.log('reply')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<CopyIcon />}
|
||||||
|
label="Copy text"
|
||||||
|
onSelect={() => console.log('copy')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<PinIcon />}
|
||||||
|
label="Pin to the channel"
|
||||||
|
onSelect={() => console.log('pin')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<ForwardIcon />}
|
||||||
|
label="Forward"
|
||||||
|
onSelect={() => console.log('forward')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<LinkIcon />}
|
||||||
|
label="Share link to message"
|
||||||
|
onSelect={() => console.log('share')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
label="Delete message"
|
||||||
|
danger
|
||||||
|
onSelect={() => console.log('delete')}
|
||||||
|
/>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { XStack } from 'tamagui'
|
||||||
|
|
||||||
|
import { Popover } from '../../popover'
|
||||||
|
import { ReactButton } from '../../react-button'
|
||||||
|
|
||||||
|
import type { PopoverProps } from '../../popover'
|
||||||
|
import type { ReactionsType } from '../types'
|
||||||
|
|
||||||
|
type Props = Omit<PopoverProps, 'children'> & {
|
||||||
|
children: React.ReactElement
|
||||||
|
reactions: ReactionsType
|
||||||
|
onOpenChange?: PopoverProps['onOpenChange']
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReactionPopover = (props: Props) => {
|
||||||
|
const { children, reactions, onOpenChange, ...popoverProps } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover {...popoverProps} onOpenChange={onOpenChange} modal={false}>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<Popover.Content>
|
||||||
|
<XStack space={2} padding={2}>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="love"
|
||||||
|
selected={reactions['love']?.has('me')}
|
||||||
|
/>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="thumbs-up"
|
||||||
|
selected={reactions['thumbs-up']?.has('me')}
|
||||||
|
/>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="thumbs-down"
|
||||||
|
selected={reactions['thumbs-down']?.has('me')}
|
||||||
|
/>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="laugh"
|
||||||
|
selected={reactions.laugh?.has('me')}
|
||||||
|
/>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="sad"
|
||||||
|
selected={reactions.sad?.has('me')}
|
||||||
|
/>
|
||||||
|
<ReactButton
|
||||||
|
variant="ghost"
|
||||||
|
size={32}
|
||||||
|
icon="angry"
|
||||||
|
selected={reactions.angry?.has('me')}
|
||||||
|
/>
|
||||||
|
</XStack>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,11 +1,21 @@
|
||||||
import { Reactions } from './reactions'
|
import { Reactions } from './reactions'
|
||||||
|
|
||||||
|
import type { ReactionsType } from '../types'
|
||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
const reactions: ReactionsType = {
|
||||||
|
love: new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-up': new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-down': new Set(['me', '1', '2', '3']),
|
||||||
|
}
|
||||||
|
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
const meta: Meta<typeof Reactions> = {
|
const meta: Meta<typeof Reactions> = {
|
||||||
title: 'messages/reactions',
|
title: 'messages/reactions',
|
||||||
component: Reactions,
|
component: Reactions,
|
||||||
|
args: {
|
||||||
|
reactions,
|
||||||
|
},
|
||||||
argTypes: {},
|
argTypes: {},
|
||||||
parameters: {
|
parameters: {
|
||||||
design: {
|
design: {
|
||||||
|
|
|
@ -1,94 +1,109 @@
|
||||||
import { cloneElement } from 'react'
|
|
||||||
|
|
||||||
import { AddReactionIcon } from '@status-im/icons/20'
|
|
||||||
import {
|
|
||||||
// AngryIcon,
|
|
||||||
LaughIcon,
|
|
||||||
LoveIcon,
|
|
||||||
SadIcon,
|
|
||||||
ThumbsDownIcon,
|
|
||||||
ThumbsUpIcon,
|
|
||||||
} from '@status-im/icons/reactions'
|
|
||||||
import { Stack, styled } from '@tamagui/core'
|
|
||||||
import { XStack } from 'tamagui'
|
import { XStack } from 'tamagui'
|
||||||
|
|
||||||
import { Paragraph } from '../../typography'
|
import { Dialog } from '../../dialog'
|
||||||
|
import { ReactButton } from '../../react-button'
|
||||||
|
import { Tooltip } from '../../tooltip/tooltip'
|
||||||
|
import { UserList } from '../../user-list'
|
||||||
|
import { ReactionPopover } from './reaction-popover'
|
||||||
|
|
||||||
import type React from 'react'
|
import type { ReactButtonProps } from '../../react-button'
|
||||||
|
import type { ReactionsType, ReactionType } from '../types'
|
||||||
// import { Pressable } from 'react-native'
|
|
||||||
|
|
||||||
const ReactButton = styled(Stack, {
|
|
||||||
name: 'ReactButton',
|
|
||||||
accessibilityRole: 'button',
|
|
||||||
|
|
||||||
cursor: 'pointer',
|
|
||||||
userSelect: 'none',
|
|
||||||
borderRadius: 8,
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
space: 4,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
flexShrink: 0,
|
|
||||||
minWidth: 36,
|
|
||||||
height: 24,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: '$neutral-20',
|
|
||||||
|
|
||||||
hoverStyle: {
|
|
||||||
borderColor: '$neutral-30',
|
|
||||||
},
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
selected: {
|
|
||||||
true: {
|
|
||||||
backgroundColor: '$neutral-30',
|
|
||||||
borderColor: '$neutral-30',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const,
|
|
||||||
})
|
|
||||||
|
|
||||||
type ReactionButtonProps = {
|
|
||||||
icon: React.ReactElement
|
|
||||||
count?: number
|
|
||||||
selected?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const ReactionButton = (props: ReactionButtonProps) => {
|
|
||||||
const { count, selected, icon } = props
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ReactButton selected={selected}>
|
|
||||||
{cloneElement(icon, { color: '$neutral-100' })}
|
|
||||||
{count && (
|
|
||||||
<Paragraph weight="medium" variant="smaller" whiteSpace="nowrap">
|
|
||||||
{count}
|
|
||||||
</Paragraph>
|
|
||||||
)}
|
|
||||||
</ReactButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
reactions?: any[]
|
reactions: ReactionsType
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Reactions = (props: Props) => {
|
export const Reactions = (props: Props) => {
|
||||||
const { reactions } = props
|
const { reactions } = props
|
||||||
|
|
||||||
|
const hasReaction = Object.values(reactions).some(value => value.size > 0)
|
||||||
|
|
||||||
|
if (hasReaction === false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<XStack space={8} flexWrap="wrap">
|
<XStack space={6} flexWrap="wrap">
|
||||||
<ReactionButton count={1} icon={<LoveIcon />} selected />
|
{Object.entries(reactions).map(([type, value]) => (
|
||||||
<ReactionButton count={10} icon={<ThumbsUpIcon />} />
|
<Reaction
|
||||||
<ReactionButton count={99} icon={<ThumbsDownIcon />} />
|
key={type}
|
||||||
<ReactionButton count={100} icon={<LaughIcon />} />
|
size="compact"
|
||||||
<ReactionButton count={100} icon={<SadIcon />} />
|
icon={type as ReactionType}
|
||||||
{/* FIX TAMAGUI BUG */}
|
count={value.size}
|
||||||
{/* <ReactionButton count={100} icon={<AngryIcon />} /> */}
|
selected={value.has('me')}
|
||||||
<ReactionButton icon={<AddReactionIcon />} />
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<ReactionPopover
|
||||||
|
reactions={reactions}
|
||||||
|
side="bottom"
|
||||||
|
align="start"
|
||||||
|
sideOffset={8}
|
||||||
|
>
|
||||||
|
<ReactButton size="compact" icon="add" selected={false} />
|
||||||
|
</ReactionPopover>
|
||||||
</XStack>
|
</XStack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Reaction = (props: ReactButtonProps) => {
|
||||||
|
return (
|
||||||
|
<Dialog press="long">
|
||||||
|
<Tooltip
|
||||||
|
side="bottom"
|
||||||
|
sideOffset={4}
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
You, Mr Gandalf, Ariana Perlona and
|
||||||
|
<button>3 more</button> reacted with {'[ICON]'}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ReactButton {...props} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Dialog.Content>
|
||||||
|
<UserList
|
||||||
|
users={[
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pedro',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1760&q=80',
|
||||||
|
address: 'zQ3...9d4Gs0',
|
||||||
|
indicator: 'online',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,50 +1,82 @@
|
||||||
import { ChatMessage } from './chat-message'
|
import { Message } from './message'
|
||||||
|
|
||||||
export * from './chat-message'
|
import type { ReactionsType } from './types'
|
||||||
|
|
||||||
|
export * from './message'
|
||||||
|
|
||||||
|
const reactions: ReactionsType = {
|
||||||
|
love: new Set(['me', '1']),
|
||||||
|
'thumbs-up': new Set(['3']),
|
||||||
|
'thumbs-down': new Set(['me', '1', '2', '3']),
|
||||||
|
}
|
||||||
|
|
||||||
export const Messages = () => {
|
export const Messages = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
<Message
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Nullam sapien sem, ornare ac, nonummy non, lobortis a, enim. Nunc tincidunt ante vitae massa. Duis ante orci, molestie vitae, vehicula venenatis, tincidunt ac, pede. Nulla accumsan, elit sit"
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
reactions={{}}
|
||||||
<ChatMessage
|
/>
|
||||||
|
<Message
|
||||||
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. "
|
||||||
|
reactions={{}}
|
||||||
|
reply
|
||||||
|
pinned
|
||||||
|
/>
|
||||||
|
<Message
|
||||||
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. "
|
||||||
|
reactions={{}}
|
||||||
|
/>
|
||||||
|
<Message
|
||||||
images={[
|
images={[
|
||||||
{
|
{
|
||||||
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
reactions={{}}
|
||||||
/>
|
/>
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
<Message
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Nullam sapien sem, ornare ac, nonummy non, lobortis a, enim. Nunc tincidunt ante vitae massa. Duis ante orci, molestie vitae, vehicula venenatis, tincidunt ac, pede. Nulla accumsan, elit sit"
|
||||||
<ChatMessage
|
reactions={reactions}
|
||||||
text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf"
|
|
||||||
reactions={['123']}
|
|
||||||
/>
|
/>
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
<Message
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam. "
|
||||||
<ChatMessage text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf" />
|
reactions={{}}
|
||||||
<ChatMessage
|
pinned
|
||||||
text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf"
|
|
||||||
reactions={['123']}
|
|
||||||
/>
|
/>
|
||||||
<ChatMessage
|
<Message
|
||||||
text="fsdjkf kasldjf ksdlfjksdlfj asdklfj sdkljf"
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam. "
|
||||||
reactions={['123']}
|
reactions={{}}
|
||||||
|
reply
|
||||||
/>
|
/>
|
||||||
<ChatMessage
|
<Message
|
||||||
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam. "
|
||||||
|
reactions={{}}
|
||||||
|
/>
|
||||||
|
<Message
|
||||||
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Nullam sapien sem, ornare ac, nonummy non, lobortis a, enim.sit"
|
||||||
|
reactions={reactions}
|
||||||
|
reply
|
||||||
|
/>
|
||||||
|
<Message
|
||||||
|
text="Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Nullam sapien sem, ornare ac, nonummy non, lobortis a, enim.sit"
|
||||||
|
reactions={reactions}
|
||||||
|
/>
|
||||||
|
<Message
|
||||||
images={[
|
images={[
|
||||||
{
|
{
|
||||||
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
reactions={{}}
|
||||||
/>
|
/>
|
||||||
<ChatMessage
|
<Message
|
||||||
images={[
|
images={[
|
||||||
{
|
{
|
||||||
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
url: 'https://images.unsplash.com/photo-1673433107234-14d1a4424658?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
reactions={{}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
import { ChatMessage } from './chat-message'
|
import { Message } from './message'
|
||||||
|
|
||||||
|
import type { ReactionsType } from './types'
|
||||||
import type { Meta, StoryObj } from '@storybook/react'
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
const meta: Meta<typeof ChatMessage> = {
|
const meta: Meta<typeof Message> = {
|
||||||
// title: 'Messages',
|
title: 'messages',
|
||||||
component: ChatMessage,
|
component: Message,
|
||||||
argTypes: {},
|
args: {
|
||||||
|
reactions: {},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
pinned: {
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
reply: {
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
design: {
|
design: {
|
||||||
type: 'figma',
|
type: 'figma',
|
||||||
|
@ -15,9 +28,13 @@ const meta: Meta<typeof ChatMessage> = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
type Story = StoryObj<typeof ChatMessage>
|
type Story = StoryObj<typeof Message>
|
||||||
|
|
||||||
const reactions = ['123']
|
const reactions: ReactionsType = {
|
||||||
|
love: new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-up': new Set(['me', '1', '2', '3']),
|
||||||
|
'thumbs-down': new Set(['me', '1', '2', '3']),
|
||||||
|
}
|
||||||
|
|
||||||
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
export const Text: Story = {
|
export const Text: Story = {
|
||||||
|
@ -34,6 +51,22 @@ export const TextWithReactions: Story = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TextWithReply: Story = {
|
||||||
|
name: 'Text + Reply',
|
||||||
|
args: {
|
||||||
|
text: 'This is a simple message.',
|
||||||
|
reply: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TextPinned: Story = {
|
||||||
|
name: 'Text + Pinned',
|
||||||
|
args: {
|
||||||
|
text: 'This is a simple message.',
|
||||||
|
pinned: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const LongText: Story = {
|
export const LongText: Story = {
|
||||||
name: 'Long text',
|
name: 'Long text',
|
||||||
args: {
|
args: {
|
|
@ -0,0 +1,127 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import { PinIcon } from '@status-im/icons/16'
|
||||||
|
import { Stack, Unspaced, XStack, YStack } from 'tamagui'
|
||||||
|
|
||||||
|
import { Author } from '../author/author'
|
||||||
|
import { Avatar } from '../avatar'
|
||||||
|
import { Image } from '../image'
|
||||||
|
import { Reply } from '../reply'
|
||||||
|
import { Paragraph } from '../typography'
|
||||||
|
import { Actions } from './components/actions'
|
||||||
|
import { Reactions } from './components/reactions'
|
||||||
|
|
||||||
|
import type { ReactionsType } from './types'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text?: React.ReactNode
|
||||||
|
images?: Array<{ url: string }>
|
||||||
|
reactions: ReactionsType
|
||||||
|
reply?: boolean
|
||||||
|
pinned?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const Message = (props: Props) => {
|
||||||
|
const { text, images, reactions, reply, pinned } = props
|
||||||
|
|
||||||
|
const [hovered, setHovered] = React.useState(false)
|
||||||
|
const [actionsOpen, setActionsOpen] = React.useState(false)
|
||||||
|
|
||||||
|
const active = actionsOpen || hovered
|
||||||
|
// <Sheet press="long">
|
||||||
|
|
||||||
|
return (
|
||||||
|
<YStack
|
||||||
|
position="relative"
|
||||||
|
alignItems="flex-start"
|
||||||
|
paddingHorizontal={8}
|
||||||
|
paddingVertical={8}
|
||||||
|
borderRadius={16}
|
||||||
|
backgroundColor={
|
||||||
|
active ? '$neutral-5' : pinned ? '$blue-50-opa-5' : undefined
|
||||||
|
}
|
||||||
|
onMouseEnter={() => setHovered(true)}
|
||||||
|
onMouseLeave={() => setHovered(false)}
|
||||||
|
>
|
||||||
|
{active && (
|
||||||
|
<Unspaced>
|
||||||
|
<Actions
|
||||||
|
reactions={reactions}
|
||||||
|
onOpenChange={setActionsOpen}
|
||||||
|
onReplyPress={() => {
|
||||||
|
console.log('reply')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Unspaced>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{reply && (
|
||||||
|
<Stack paddingLeft={16} paddingBottom={12}>
|
||||||
|
<Reply
|
||||||
|
type="text"
|
||||||
|
name="Alisher"
|
||||||
|
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{pinned && (
|
||||||
|
<Stack
|
||||||
|
flexDirection="row"
|
||||||
|
alignItems="center"
|
||||||
|
paddingLeft={40}
|
||||||
|
paddingBottom={2}
|
||||||
|
space={2}
|
||||||
|
>
|
||||||
|
<PinIcon color="$blue-50" />
|
||||||
|
<Paragraph variant={11} weight="medium" color="$blue-50">
|
||||||
|
Steve
|
||||||
|
</Paragraph>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<XStack space={10}>
|
||||||
|
<Avatar
|
||||||
|
size={32}
|
||||||
|
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
||||||
|
indicator="online"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<YStack flex={1}>
|
||||||
|
<Author
|
||||||
|
name="Alisher Yakupov"
|
||||||
|
address="zQ3...9d4Gs0"
|
||||||
|
status="verified"
|
||||||
|
time="09:30"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{text && (
|
||||||
|
<Paragraph flexGrow={0} weight="regular" color="$neutral-100">
|
||||||
|
{text}
|
||||||
|
</Paragraph>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{images?.map(image => (
|
||||||
|
<Stack
|
||||||
|
key={image.url}
|
||||||
|
marginTop={8}
|
||||||
|
$gtMd={{
|
||||||
|
maxWidth: 320,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image src={image.url} width="full" height={320} radius={12} />
|
||||||
|
</Stack>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{reactions && (
|
||||||
|
<Stack paddingTop={8}>
|
||||||
|
<Reactions reactions={reactions} />
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</YStack>
|
||||||
|
</XStack>
|
||||||
|
</YStack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Message }
|
|
@ -0,0 +1,12 @@
|
||||||
|
export type ReactionType =
|
||||||
|
| 'love'
|
||||||
|
| 'laugh'
|
||||||
|
| 'thumbs-up'
|
||||||
|
| 'thumbs-down'
|
||||||
|
| 'sad'
|
||||||
|
| 'angry'
|
||||||
|
| 'add'
|
||||||
|
|
||||||
|
export type ReactionsType = {
|
||||||
|
[key in ReactionType]?: Set<string>
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export { type PopoverProps, Popover } from './popover'
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { Popover } from './popover'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
|
const meta: Meta<typeof Popover> = {
|
||||||
|
// title: 'Messages',
|
||||||
|
component: Popover,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Web?node-id=611%3A36006&t=Gyy71OAckl3b2TWj-4',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Popover>
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {},
|
||||||
|
render: args => (
|
||||||
|
<Popover {...args}>
|
||||||
|
<Button type="primary">Trigger</Button>
|
||||||
|
<Popover.Content>some content</Popover.Content>
|
||||||
|
</Popover>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover'
|
||||||
|
import { Stack } from 'tamagui'
|
||||||
|
|
||||||
|
import type { PopoverContentProps } from '@radix-ui/react-popover'
|
||||||
|
import type { FunctionComponent } from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: [React.ReactElement, React.ReactElement]
|
||||||
|
onOpenChange?: (open: boolean) => void
|
||||||
|
modal?: false
|
||||||
|
side?: PopoverContentProps['side']
|
||||||
|
sideOffset?: PopoverContentProps['sideOffset']
|
||||||
|
align?: PopoverContentProps['align']
|
||||||
|
alignOffset?: PopoverContentProps['alignOffset']
|
||||||
|
}
|
||||||
|
|
||||||
|
const Popover = (props: Props) => {
|
||||||
|
const { children, onOpenChange, modal, ...contentProps } = props
|
||||||
|
|
||||||
|
const [trigger, content] = children
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Root onOpenChange={onOpenChange} modal={modal}>
|
||||||
|
<Trigger asChild>{trigger}</Trigger>
|
||||||
|
<Portal>
|
||||||
|
<Content {...contentProps}>{content}</Content>
|
||||||
|
</Portal>
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PopoverContent: FunctionComponent = props => {
|
||||||
|
const { children } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack
|
||||||
|
backgroundColor="$white-100"
|
||||||
|
borderRadius={12}
|
||||||
|
shadowRadius={30}
|
||||||
|
shadowOffset="0px 8px"
|
||||||
|
shadowColor="rgba(9, 16, 28, 0.12)"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Popover.Content = PopoverContent
|
||||||
|
|
||||||
|
export { Popover as Popover }
|
||||||
|
export type { Props as PopoverProps }
|
|
@ -0,0 +1 @@
|
||||||
|
export { type ReactButtonProps, ReactButton } from './react-button'
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { XStack } from 'tamagui'
|
||||||
|
|
||||||
|
import { ReactButton } from './react-button'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
|
const meta: Meta<typeof ReactButton> = {
|
||||||
|
title: 'ReactButton',
|
||||||
|
component: ReactButton,
|
||||||
|
args: {},
|
||||||
|
argTypes: {},
|
||||||
|
render: args => (
|
||||||
|
<XStack space={4}>
|
||||||
|
<ReactButton {...args} icon="laugh" />
|
||||||
|
<ReactButton {...args} icon="love" />
|
||||||
|
<ReactButton {...args} icon="sad" />
|
||||||
|
<ReactButton {...args} icon="thumbs-up" />
|
||||||
|
<ReactButton {...args} icon="thumbs-down" />
|
||||||
|
<ReactButton {...args} icon="angry" />
|
||||||
|
</XStack>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof ReactButton>
|
||||||
|
|
||||||
|
export const Outline: Story = {
|
||||||
|
name: 'Outline / 40px',
|
||||||
|
args: { variant: 'outline' },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OutlineSelected: Story = {
|
||||||
|
name: 'Outline / 40px / selected',
|
||||||
|
args: { variant: 'outline', selected: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Outline32: Story = {
|
||||||
|
name: 'Outline / 32px',
|
||||||
|
args: { variant: 'outline', size: 32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Outline32Selected: Story = {
|
||||||
|
name: 'Outline / 32px',
|
||||||
|
args: { variant: 'outline', size: 32, selected: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Ghost: Story = {
|
||||||
|
name: 'Ghost / 40px',
|
||||||
|
args: { variant: 'ghost' },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GhostSelected: Story = {
|
||||||
|
name: 'Ghost / 40px / selected',
|
||||||
|
args: { variant: 'ghost', selected: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Ghost32: Story = {
|
||||||
|
name: 'Ghost / 32px',
|
||||||
|
args: { variant: 'ghost', size: 32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Ghost32Selected: Story = {
|
||||||
|
name: 'Ghost / 32px',
|
||||||
|
args: { variant: 'ghost', size: 32, selected: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,141 @@
|
||||||
|
import { forwardRef } from 'react'
|
||||||
|
|
||||||
|
import { AddReactionIcon } from '@status-im/icons/20'
|
||||||
|
import {
|
||||||
|
AngryIcon,
|
||||||
|
LaughIcon,
|
||||||
|
LoveIcon,
|
||||||
|
SadIcon,
|
||||||
|
ThumbsDownIcon,
|
||||||
|
ThumbsUpIcon,
|
||||||
|
} from '@status-im/icons/reactions'
|
||||||
|
import { Stack, styled } from '@tamagui/core'
|
||||||
|
|
||||||
|
import { Paragraph } from '../typography'
|
||||||
|
|
||||||
|
import type { GetProps } from '@tamagui/core'
|
||||||
|
import type { Ref } from 'react'
|
||||||
|
import type { PressableProps } from 'react-native'
|
||||||
|
|
||||||
|
const Button = styled(Stack, {
|
||||||
|
name: 'ReactButton',
|
||||||
|
accessibilityRole: 'button',
|
||||||
|
|
||||||
|
cursor: 'pointer',
|
||||||
|
userSelect: 'none',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
borderWidth: 1,
|
||||||
|
animation: 'fast',
|
||||||
|
space: 4,
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
outline: {
|
||||||
|
borderColor: '$neutral-10',
|
||||||
|
hoverStyle: { borderColor: '$neutral-30' },
|
||||||
|
pressStyle: {
|
||||||
|
backgroundColor: '$neutral-10',
|
||||||
|
borderColor: '$neutral-20',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
ghost: {
|
||||||
|
borderColor: 'transparent',
|
||||||
|
hoverStyle: { backgroundColor: '$neutral-10' },
|
||||||
|
pressStyle: { backgroundColor: '$neutral-20' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
selected: {
|
||||||
|
true: {
|
||||||
|
backgroundColor: '$neutral-10',
|
||||||
|
borderColor: '$neutral-30',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
size: {
|
||||||
|
40: {
|
||||||
|
borderRadius: 12,
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
|
|
||||||
|
32: {
|
||||||
|
borderRadius: 10,
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
},
|
||||||
|
|
||||||
|
compact: {
|
||||||
|
borderRadius: 8,
|
||||||
|
minWidth: 36,
|
||||||
|
height: 24,
|
||||||
|
paddingHorizontal: 8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const,
|
||||||
|
})
|
||||||
|
|
||||||
|
type ButtonProps = GetProps<typeof Button>
|
||||||
|
|
||||||
|
export const REACTIONS = {
|
||||||
|
love: LoveIcon,
|
||||||
|
laugh: LaughIcon,
|
||||||
|
'thumbs-up': ThumbsUpIcon,
|
||||||
|
'thumbs-down': ThumbsDownIcon,
|
||||||
|
sad: SadIcon,
|
||||||
|
angry: AngryIcon,
|
||||||
|
add: AddReactionIcon,
|
||||||
|
} as const
|
||||||
|
|
||||||
|
interface Props extends PressableProps {
|
||||||
|
icon: keyof typeof REACTIONS
|
||||||
|
variant?: ButtonProps['variant']
|
||||||
|
size?: ButtonProps['size']
|
||||||
|
// FIXME: use aria-selected
|
||||||
|
selected?: boolean
|
||||||
|
count?: number
|
||||||
|
// FIXME: update to latest RN
|
||||||
|
'aria-expanded'?: boolean
|
||||||
|
'aria-selected'?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const ReactButton = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||||
|
const {
|
||||||
|
icon,
|
||||||
|
variant = 'outline',
|
||||||
|
size = 40,
|
||||||
|
count,
|
||||||
|
...pressableProps
|
||||||
|
} = props
|
||||||
|
|
||||||
|
const Icon = REACTIONS[icon]
|
||||||
|
|
||||||
|
const selected =
|
||||||
|
props.selected || props['aria-expanded'] || props['aria-selected']
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
{...(pressableProps as any)}
|
||||||
|
ref={ref}
|
||||||
|
variant={variant}
|
||||||
|
size={size}
|
||||||
|
selected={selected}
|
||||||
|
>
|
||||||
|
<Icon color="$neutral-100" />
|
||||||
|
{count && (
|
||||||
|
<Paragraph weight="medium" variant="smaller" whiteSpace="nowrap">
|
||||||
|
{count}
|
||||||
|
</Paragraph>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _ReactButton = forwardRef(ReactButton)
|
||||||
|
|
||||||
|
export { _ReactButton as ReactButton }
|
||||||
|
export type { Props as ReactButtonProps }
|
|
@ -0,0 +1 @@
|
||||||
|
export { type ReplyProps, Reply } from './reply'
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { action } from '@storybook/addon-actions'
|
||||||
|
|
||||||
|
import { Reply } from './reply'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
const meta: Meta<typeof Reply> = {
|
||||||
|
component: Reply,
|
||||||
|
argTypes: {},
|
||||||
|
args: {
|
||||||
|
name: 'Alisher Yakupov',
|
||||||
|
src: 'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?ixid=Mnw0MDAxMTJ8MHwxfHNlYXJjaHw0fHxhdmF0YXJ8ZW58MHx8fHwxNjc1MjU4NTkw&ixlib=rb-4.0.3',
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Desktop%2FWeb?node-id=3173%3A55936&t=QgRAQPXVREVsrDg7-11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Reply>
|
||||||
|
|
||||||
|
export const Text: Story = {
|
||||||
|
args: {
|
||||||
|
type: 'text',
|
||||||
|
onClose: undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TextClose: Story = {
|
||||||
|
name: 'Text + Close',
|
||||||
|
args: {
|
||||||
|
...Text.args,
|
||||||
|
onClose: action('close'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Image: Story = {
|
||||||
|
args: {
|
||||||
|
type: 'image',
|
||||||
|
onClose: undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImageClose: Story = {
|
||||||
|
name: 'Image + Close',
|
||||||
|
args: {
|
||||||
|
...Image.args,
|
||||||
|
onClose: action('close'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GIF: Story = {
|
||||||
|
args: {
|
||||||
|
type: 'gif',
|
||||||
|
onClose: undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GIFClose: Story = {
|
||||||
|
name: 'GIF + Close',
|
||||||
|
args: {
|
||||||
|
...GIF.args,
|
||||||
|
onClose: action('close'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Deleted: Story = {
|
||||||
|
args: {
|
||||||
|
type: 'deleted',
|
||||||
|
onClose: undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeletedClose: Story = {
|
||||||
|
name: 'Deleted + Close',
|
||||||
|
args: {
|
||||||
|
type: 'deleted',
|
||||||
|
onClose: action('close'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { CloseIcon } from '@status-im/icons/12'
|
||||||
|
import { SadIcon } from '@status-im/icons/16'
|
||||||
|
import { Path, Svg } from 'react-native-svg'
|
||||||
|
import { Stack, Unspaced, XStack } from 'tamagui'
|
||||||
|
|
||||||
|
import { Avatar } from '../avatar'
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { Paragraph } from '../typography'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
type: 'text' | 'gif' | 'image' | 'deleted'
|
||||||
|
onClose?: VoidFunction
|
||||||
|
name: string
|
||||||
|
src: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This should accept message or message ID and render the message accordingly
|
||||||
|
const Reply = (props: Props) => {
|
||||||
|
const { type, name, onClose, src } = props
|
||||||
|
|
||||||
|
const content =
|
||||||
|
type !== 'deleted' ? (
|
||||||
|
<XStack position="relative" space={4} alignItems="center" height={24}>
|
||||||
|
<Unspaced>
|
||||||
|
<Stack position="absolute" left={-24} top={10}>
|
||||||
|
<Connector />
|
||||||
|
</Stack>
|
||||||
|
</Unspaced>
|
||||||
|
|
||||||
|
<Avatar size={20} src={src} />
|
||||||
|
|
||||||
|
<Paragraph variant="smaller" weight="semibold" color="$neutral-100">
|
||||||
|
{name}
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
<Paragraph variant={11} weight="regular" color="$neutral-50">
|
||||||
|
{type === 'text' && 'What is the meaning of life? '}
|
||||||
|
{type === 'gif' && 'GIF'}
|
||||||
|
{type === 'image' && '5 photos'}
|
||||||
|
</Paragraph>
|
||||||
|
</XStack>
|
||||||
|
) : (
|
||||||
|
<XStack position="relative" space={4} alignItems="center" height={24}>
|
||||||
|
<Unspaced>
|
||||||
|
<Stack position="absolute" left={-24} top={10}>
|
||||||
|
<Connector />
|
||||||
|
</Stack>
|
||||||
|
</Unspaced>
|
||||||
|
|
||||||
|
<SadIcon color="$neutral-50" />
|
||||||
|
|
||||||
|
<Paragraph variant="smaller" weight="medium" color="$neutral-50">
|
||||||
|
Message deleted
|
||||||
|
</Paragraph>
|
||||||
|
</XStack>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<XStack
|
||||||
|
space={8}
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
paddingLeft={24}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
|
||||||
|
{/* FIXME: This should be regular button with size 24 */}
|
||||||
|
{onClose && (
|
||||||
|
<Button
|
||||||
|
type="outline"
|
||||||
|
size={24}
|
||||||
|
icon={<CloseIcon />}
|
||||||
|
onPress={onClose}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</XStack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Connector = () => (
|
||||||
|
<Svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<Path
|
||||||
|
d="M16 1V1C8.16344 1 1 8.16344 1 16V16"
|
||||||
|
stroke="#A1ABBD"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
</Svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export { Reply }
|
||||||
|
export type { Props as ReplyProps }
|
|
@ -0,0 +1 @@
|
||||||
|
export { Sheet } from './sheet'
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { Sheet } from './sheet'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
|
const meta: Meta<typeof Sheet> = {
|
||||||
|
// title: 'Messages',
|
||||||
|
component: Sheet,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Web?node-id=611%3A36006&t=Gyy71OAckl3b2TWj-4',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Sheet>
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {},
|
||||||
|
render: args => (
|
||||||
|
<Sheet {...args}>
|
||||||
|
<Button>Trigger</Button>
|
||||||
|
<Sheet.Content>hello</Sheet.Content>
|
||||||
|
</Sheet>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { Content, Overlay, Portal, Root, Trigger } from '@radix-ui/react-dialog'
|
||||||
|
|
||||||
|
import type React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: [React.ReactElement, React.ReactElement]
|
||||||
|
open?: boolean
|
||||||
|
onOpenChange?: (open: boolean) => void
|
||||||
|
press?: 'normal' | 'long'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sheet = (props: Props) => {
|
||||||
|
const { children, open, onOpenChange } = props
|
||||||
|
|
||||||
|
const [trigger, content] = children
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Root open={open} onOpenChange={onOpenChange}>
|
||||||
|
{/* TRIGGER */}
|
||||||
|
<Trigger asChild>{trigger}</Trigger>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<Portal>
|
||||||
|
<Overlay
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
inset: 0,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{content}
|
||||||
|
</Portal>
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DialogContentProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
initialFocusRef?: React.RefObject<HTMLElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
const SheetContent = (props: DialogContentProps) => {
|
||||||
|
const { children, initialFocusRef } = props
|
||||||
|
|
||||||
|
const handleOpenAutoFocus = (event: Event) => {
|
||||||
|
if (initialFocusRef?.current) {
|
||||||
|
event.preventDefault()
|
||||||
|
initialFocusRef.current.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Content
|
||||||
|
onOpenAutoFocus={handleOpenAutoFocus}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'white',
|
||||||
|
padding: 8,
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8,
|
||||||
|
position: 'fixed',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
height: '80%',
|
||||||
|
// top: 'auto',
|
||||||
|
// from
|
||||||
|
// transform: 'translate3d(0,100%,0)',
|
||||||
|
// to
|
||||||
|
transform: 'translate3d(0,0,0)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Content>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Sheet.Content = SheetContent
|
||||||
|
|
||||||
|
export { Sheet }
|
|
@ -0,0 +1 @@
|
||||||
|
export { type TooltipProps, Tooltip } from './tooltip'
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { PropsWithChildren } from 'react'
|
||||||
|
|
||||||
|
export const Tooltip = ({ children }: PropsWithChildren<unknown>) => children
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Button } from '../button'
|
||||||
|
import { Tooltip } from './tooltip'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
const meta: Meta<typeof Tooltip> = {
|
||||||
|
component: Tooltip,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {
|
||||||
|
design: {
|
||||||
|
type: 'figma',
|
||||||
|
url: 'https://www.figma.com/file/IBmFKgGL1B4GzqD8LQTw6n/Design-System-for-Web?node-id=15032%3A174184&t=PHVNitU0s0KwOi8L-0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Tooltip>
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
content: 'Sebastian Vettel reacted with a heart',
|
||||||
|
},
|
||||||
|
render: args => (
|
||||||
|
<Tooltip {...args}>
|
||||||
|
<Button type="outline">Trigger</Button>
|
||||||
|
</Tooltip>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { forwardRef } from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Arrow,
|
||||||
|
Content,
|
||||||
|
Portal,
|
||||||
|
Root,
|
||||||
|
TooltipProvider,
|
||||||
|
Trigger,
|
||||||
|
} from '@radix-ui/react-tooltip'
|
||||||
|
import { Stack } from 'tamagui'
|
||||||
|
|
||||||
|
import { Paragraph } from '../typography'
|
||||||
|
|
||||||
|
import type { TooltipContentProps } from '@radix-ui/react-tooltip'
|
||||||
|
import type { Ref } from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: React.ReactElement
|
||||||
|
content: React.ReactNode
|
||||||
|
delayDuration?: number
|
||||||
|
side?: TooltipContentProps['side']
|
||||||
|
sideOffset?: TooltipContentProps['sideOffset']
|
||||||
|
align?: TooltipContentProps['align']
|
||||||
|
alignOffset?: TooltipContentProps['alignOffset']
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tooltip = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
content,
|
||||||
|
delayDuration,
|
||||||
|
side,
|
||||||
|
sideOffset,
|
||||||
|
align,
|
||||||
|
alignOffset,
|
||||||
|
...triggerProps
|
||||||
|
} = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipProvider>
|
||||||
|
<Root delayDuration={delayDuration}>
|
||||||
|
<Trigger {...triggerProps} ref={ref} asChild>
|
||||||
|
{children}
|
||||||
|
</Trigger>
|
||||||
|
|
||||||
|
<Portal>
|
||||||
|
<Content
|
||||||
|
asChild
|
||||||
|
side={side}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
align={align}
|
||||||
|
alignOffset={alignOffset}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
backgroundColor="$neutral-95"
|
||||||
|
paddingVertical={6}
|
||||||
|
paddingHorizontal={12}
|
||||||
|
borderRadius={8}
|
||||||
|
shadowRadius={30}
|
||||||
|
shadowOffset="0px 8px"
|
||||||
|
shadowColor="rgba(9, 16, 28, 0.12)"
|
||||||
|
>
|
||||||
|
{typeof content === 'string' ? (
|
||||||
|
<Paragraph variant="smaller" weight="medium" color="$white-100">
|
||||||
|
{content}
|
||||||
|
</Paragraph>
|
||||||
|
) : (
|
||||||
|
content
|
||||||
|
)}
|
||||||
|
<Arrow width={11} height={5} />
|
||||||
|
</Stack>
|
||||||
|
</Content>
|
||||||
|
</Portal>
|
||||||
|
</Root>
|
||||||
|
</TooltipProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Tooltip = forwardRef(Tooltip)
|
||||||
|
|
||||||
|
export { _Tooltip as Tooltip }
|
||||||
|
export type { Props as TooltipProps }
|
|
@ -1,13 +1,21 @@
|
||||||
import { Divider, IconButton, Paragraph } from '@status-im/components'
|
import { Divider, IconButton, Paragraph } from '@status-im/components'
|
||||||
import {
|
import {
|
||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
|
CommunitiesIcon,
|
||||||
|
DeleteIcon,
|
||||||
|
DownloadIcon,
|
||||||
LockedIcon,
|
LockedIcon,
|
||||||
MembersIcon,
|
MembersIcon,
|
||||||
|
MutedIcon,
|
||||||
OptionsIcon,
|
OptionsIcon,
|
||||||
|
ShareIcon,
|
||||||
|
UpToDateIcon,
|
||||||
} from '@status-im/icons/20'
|
} from '@status-im/icons/20'
|
||||||
import { Stack } from '@tamagui/core'
|
import { Stack } from '@tamagui/core'
|
||||||
import { BlurView } from 'expo-blur'
|
import { BlurView } from 'expo-blur'
|
||||||
|
|
||||||
|
import { DropdownMenu } from '../dropdown-menu'
|
||||||
|
|
||||||
import type { GetProps, StackProps } from '@tamagui/core'
|
import type { GetProps, StackProps } from '@tamagui/core'
|
||||||
|
|
||||||
type BaseProps = GetProps<typeof Stack>
|
type BaseProps = GetProps<typeof Stack>
|
||||||
|
@ -104,7 +112,46 @@ const Topbar = (props: Props) => {
|
||||||
blurred={isBlurred}
|
blurred={isBlurred}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<IconButton icon={<OptionsIcon />} blurred={isBlurred} />
|
<DropdownMenu>
|
||||||
|
<IconButton icon={<OptionsIcon />} />
|
||||||
|
|
||||||
|
<DropdownMenu.Content align="end" sideOffset={4}>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<CommunitiesIcon />}
|
||||||
|
label="View channel members and details"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<MutedIcon />}
|
||||||
|
label="Mute channel"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<UpToDateIcon />}
|
||||||
|
label="Mark as read"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<DownloadIcon />}
|
||||||
|
label="Fetch messages"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
/>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<ShareIcon />}
|
||||||
|
label="Share link to the channel"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
label="Clear history"
|
||||||
|
onSelect={() => console.log('click')}
|
||||||
|
danger
|
||||||
|
/>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</BlurView>
|
</BlurView>
|
||||||
|
|
|
@ -23,7 +23,6 @@ export default defineConfig(({ mode }) => {
|
||||||
'./src/reactions/index.ts',
|
'./src/reactions/index.ts',
|
||||||
],
|
],
|
||||||
fileName(format, entryName) {
|
fileName(format, entryName) {
|
||||||
console.log('fileName > format, entryName', format, entryName)
|
|
||||||
// const [name] = entryName.split('/')
|
// const [name] = entryName.split('/')
|
||||||
return `icons-${entryName}.${format}.js`
|
return `icons-${entryName}.${format}.js`
|
||||||
},
|
},
|
||||||
|
|
224
yarn.lock
224
yarn.lock
|
@ -3612,6 +3612,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-primitive" "1.0.0"
|
"@radix-ui/react-primitive" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-arrow@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4"
|
||||||
|
integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/react-checkbox@^0.1.5":
|
"@radix-ui/react-checkbox@^0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-0.1.5.tgz#3a6bd54ba1720c8e5c03852acf460e35dfbe9da3"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-0.1.5.tgz#3a6bd54ba1720c8e5c03852acf460e35dfbe9da3"
|
||||||
|
@ -3665,6 +3673,17 @@
|
||||||
"@radix-ui/react-primitive" "1.0.0"
|
"@radix-ui/react-primitive" "1.0.0"
|
||||||
"@radix-ui/react-slot" "1.0.0"
|
"@radix-ui/react-slot" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-collection@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5"
|
||||||
|
integrity sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-slot" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/react-compose-refs@0.1.0", "@radix-ui/react-compose-refs@^0.1.0":
|
"@radix-ui/react-compose-refs@0.1.0", "@radix-ui/react-compose-refs@^0.1.0":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.0.tgz#cff6e780a0f73778b976acff2c2a5b6551caab95"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-0.1.0.tgz#cff6e780a0f73778b976acff2c2a5b6551caab95"
|
||||||
|
@ -3758,6 +3777,18 @@
|
||||||
"@radix-ui/react-use-callback-ref" "1.0.0"
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
"@radix-ui/react-use-escape-keydown" "1.0.0"
|
"@radix-ui/react-use-escape-keydown" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-dismissable-layer@1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2"
|
||||||
|
integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
"@radix-ui/react-use-escape-keydown" "1.0.2"
|
||||||
|
|
||||||
"@radix-ui/react-dropdown-menu@^0.1.6":
|
"@radix-ui/react-dropdown-menu@^0.1.6":
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.1.6.tgz#3203229788cd57e552c9f19dcc7008e2b545919c"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.1.6.tgz#3203229788cd57e552c9f19dcc7008e2b545919c"
|
||||||
|
@ -3772,6 +3803,20 @@
|
||||||
"@radix-ui/react-primitive" "0.1.4"
|
"@radix-ui/react-primitive" "0.1.4"
|
||||||
"@radix-ui/react-use-controllable-state" "0.1.0"
|
"@radix-ui/react-use-controllable-state" "0.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-dropdown-menu@^2.0.2":
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.2.tgz#758ca7733dc79b3a6523d2d5a8d33970ec7ece1b"
|
||||||
|
integrity sha512-r0kN0fstrSi+uAdK2GkLxnnbhqVBy/9Q4o4PvGOYipW0BldQlYBMSmZprvCNj2i2mAATx16kvzIn12GnaGjbMw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-id" "1.0.0"
|
||||||
|
"@radix-ui/react-menu" "2.0.2"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-focus-guards@0.1.0":
|
"@radix-ui/react-focus-guards@0.1.0":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.1.0.tgz#ba3b6f902cba7826569f8edc21ff8223dece7def"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-0.1.0.tgz#ba3b6f902cba7826569f8edc21ff8223dece7def"
|
||||||
|
@ -3779,6 +3824,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
|
"@radix-ui/react-focus-guards@1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa"
|
||||||
|
integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
|
||||||
"@radix-ui/react-focus-scope@0.1.4":
|
"@radix-ui/react-focus-scope@0.1.4":
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.1.4.tgz#c830724e212d42ffaaa81aee49533213d09b47df"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.1.4.tgz#c830724e212d42ffaaa81aee49533213d09b47df"
|
||||||
|
@ -3789,6 +3841,16 @@
|
||||||
"@radix-ui/react-primitive" "0.1.4"
|
"@radix-ui/react-primitive" "0.1.4"
|
||||||
"@radix-ui/react-use-callback-ref" "0.1.0"
|
"@radix-ui/react-use-callback-ref" "0.1.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-focus-scope@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951"
|
||||||
|
integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-id@0.1.5":
|
"@radix-ui/react-id@0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-0.1.5.tgz#010d311bedd5a2884c1e9bb6aaaa4e6cc1d1d3b8"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-0.1.5.tgz#010d311bedd5a2884c1e9bb6aaaa4e6cc1d1d3b8"
|
||||||
|
@ -3840,6 +3902,31 @@
|
||||||
aria-hidden "^1.1.1"
|
aria-hidden "^1.1.1"
|
||||||
react-remove-scroll "^2.4.0"
|
react-remove-scroll "^2.4.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-menu@2.0.2":
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.0.2.tgz#54d4e040407962af95ff3c66612749661a504de7"
|
||||||
|
integrity sha512-H5dtBi/k3tc45IMd2Pu+Q2PyONFlsYJ5sWUlflSs8BQRghh5GhJHLRuB1yb88VOywuzzvGkaR/HUJJ65Jf2POA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-collection" "1.0.1"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-direction" "1.0.0"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.0.2"
|
||||||
|
"@radix-ui/react-focus-guards" "1.0.0"
|
||||||
|
"@radix-ui/react-focus-scope" "1.0.1"
|
||||||
|
"@radix-ui/react-id" "1.0.0"
|
||||||
|
"@radix-ui/react-popper" "1.1.0"
|
||||||
|
"@radix-ui/react-portal" "1.0.1"
|
||||||
|
"@radix-ui/react-presence" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-roving-focus" "1.0.2"
|
||||||
|
"@radix-ui/react-slot" "1.0.1"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "2.5.5"
|
||||||
|
|
||||||
"@radix-ui/react-popover@^0.1.6":
|
"@radix-ui/react-popover@^0.1.6":
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-0.1.6.tgz#788e969239d9c55239678e615ab591b6b7ba5cdc"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-0.1.6.tgz#788e969239d9c55239678e615ab591b6b7ba5cdc"
|
||||||
|
@ -3861,6 +3948,28 @@
|
||||||
aria-hidden "^1.1.1"
|
aria-hidden "^1.1.1"
|
||||||
react-remove-scroll "^2.4.0"
|
react-remove-scroll "^2.4.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-popover@^1.0.3":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe"
|
||||||
|
integrity sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.0.2"
|
||||||
|
"@radix-ui/react-focus-guards" "1.0.0"
|
||||||
|
"@radix-ui/react-focus-scope" "1.0.1"
|
||||||
|
"@radix-ui/react-id" "1.0.0"
|
||||||
|
"@radix-ui/react-popper" "1.1.0"
|
||||||
|
"@radix-ui/react-portal" "1.0.1"
|
||||||
|
"@radix-ui/react-presence" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-slot" "1.0.1"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "2.5.5"
|
||||||
|
|
||||||
"@radix-ui/react-popper@0.1.4":
|
"@radix-ui/react-popper@0.1.4":
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.1.4.tgz#dfc055dcd7dfae6a2eff7a70d333141d15a5d029"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.1.4.tgz#dfc055dcd7dfae6a2eff7a70d333141d15a5d029"
|
||||||
|
@ -3892,6 +4001,23 @@
|
||||||
"@radix-ui/react-use-size" "1.0.0"
|
"@radix-ui/react-use-size" "1.0.0"
|
||||||
"@radix-ui/rect" "1.0.0"
|
"@radix-ui/rect" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-popper@1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60"
|
||||||
|
integrity sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@floating-ui/react-dom" "0.7.2"
|
||||||
|
"@radix-ui/react-arrow" "1.0.1"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
"@radix-ui/react-use-layout-effect" "1.0.0"
|
||||||
|
"@radix-ui/react-use-rect" "1.0.0"
|
||||||
|
"@radix-ui/react-use-size" "1.0.0"
|
||||||
|
"@radix-ui/rect" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-portal@0.1.4":
|
"@radix-ui/react-portal@0.1.4":
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2"
|
||||||
|
@ -3909,6 +4035,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-primitive" "1.0.0"
|
"@radix-ui/react-primitive" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-portal@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33"
|
||||||
|
integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/react-presence@0.1.2":
|
"@radix-ui/react-presence@0.1.2":
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.1.2.tgz#9f11cce3df73cf65bc348e8b76d891f0d54c1fe3"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.1.2.tgz#9f11cce3df73cf65bc348e8b76d891f0d54c1fe3"
|
||||||
|
@ -3943,6 +4077,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-slot" "1.0.0"
|
"@radix-ui/react-slot" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-primitive@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a"
|
||||||
|
integrity sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-slot" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/react-roving-focus@0.1.5":
|
"@radix-ui/react-roving-focus@0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.1.5.tgz#cc48d17a36b56f253d54905b0fd60ee134cb97ee"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.1.5.tgz#cc48d17a36b56f253d54905b0fd60ee134cb97ee"
|
||||||
|
@ -3974,6 +4116,22 @@
|
||||||
"@radix-ui/react-use-callback-ref" "1.0.0"
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
"@radix-ui/react-use-controllable-state" "1.0.0"
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-roving-focus@1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de"
|
||||||
|
integrity sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-collection" "1.0.1"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-direction" "1.0.0"
|
||||||
|
"@radix-ui/react-id" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-separator@^0.1.4":
|
"@radix-ui/react-separator@^0.1.4":
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-0.1.4.tgz#383ad0f82b364d9982a978d752084af3598e4090"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-0.1.4.tgz#383ad0f82b364d9982a978d752084af3598e4090"
|
||||||
|
@ -3998,6 +4156,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-compose-refs" "1.0.0"
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-slot@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81"
|
||||||
|
integrity sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-tabs@^1.0.0":
|
"@radix-ui/react-tabs@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.0.tgz#135c67f1f2bd9ada69a3f6e38dd897d459af5fe5"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.0.tgz#135c67f1f2bd9ada69a3f6e38dd897d459af5fe5"
|
||||||
|
@ -4073,6 +4239,25 @@
|
||||||
"@radix-ui/react-use-controllable-state" "1.0.0"
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
"@radix-ui/react-visually-hidden" "1.0.0"
|
"@radix-ui/react-visually-hidden" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip@^1.0.3":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.3.tgz#a8c7e7b2b542cdfe7e94122af79079f7de3f90ff"
|
||||||
|
integrity sha512-cmc9qV4KpgqdXVTn1K8KN8MnuSXvw+E719pKwyvpCGrQ+0AA2qTjcIL3uxCj4jc4k3sDR36RF7R3H7N5hPybBQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.0"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.0"
|
||||||
|
"@radix-ui/react-context" "1.0.0"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.0.2"
|
||||||
|
"@radix-ui/react-id" "1.0.0"
|
||||||
|
"@radix-ui/react-popper" "1.1.0"
|
||||||
|
"@radix-ui/react-portal" "1.0.1"
|
||||||
|
"@radix-ui/react-presence" "1.0.0"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-slot" "1.0.1"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.0.0"
|
||||||
|
"@radix-ui/react-visually-hidden" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/react-use-body-pointer-events@0.1.1":
|
"@radix-ui/react-use-body-pointer-events@0.1.1":
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597"
|
||||||
|
@ -4134,6 +4319,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-use-callback-ref" "1.0.0"
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-use-escape-keydown@1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6"
|
||||||
|
integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-use-callback-ref" "1.0.0"
|
||||||
|
|
||||||
"@radix-ui/react-use-layout-effect@0.1.0":
|
"@radix-ui/react-use-layout-effect@0.1.0":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.0.tgz#ebf71bd6d2825de8f1fbb984abf2293823f0f223"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-0.1.0.tgz#ebf71bd6d2825de8f1fbb984abf2293823f0f223"
|
||||||
|
@ -4202,6 +4395,14 @@
|
||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-primitive" "1.0.0"
|
"@radix-ui/react-primitive" "1.0.0"
|
||||||
|
|
||||||
|
"@radix-ui/react-visually-hidden@1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.1.tgz#9a4ac4fc97ae8d72a10e727f16b3121b5f0aa469"
|
||||||
|
integrity sha512-K1hJcCMfWfiYUibRqf3V8r5Drpyf7rh44jnrwAbdvI5iCCijilBBeyQv9SKidYNZIopMdCyR9FnIjkHxHN0FcQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/react-primitive" "1.0.1"
|
||||||
|
|
||||||
"@radix-ui/rect@0.1.1":
|
"@radix-ui/rect@0.1.1":
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"
|
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"
|
||||||
|
@ -14437,6 +14638,7 @@ node-fetch-native@^1.0.1:
|
||||||
|
|
||||||
node-fetch@2.6.7, node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.x.x:
|
node-fetch@2.6.7, node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.x.x:
|
||||||
version "2.6.7"
|
version "2.6.7"
|
||||||
|
uid "1b5d62978f2ed07b99444f64f0df39f960a6d34d"
|
||||||
resolved "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz#1b5d62978f2ed07b99444f64f0df39f960a6d34d"
|
resolved "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz#1b5d62978f2ed07b99444f64f0df39f960a6d34d"
|
||||||
|
|
||||||
node-forge@^1.1.0, node-forge@^1.2.1, node-forge@^1.3.1:
|
node-forge@^1.1.0, node-forge@^1.2.1, node-forge@^1.3.1:
|
||||||
|
@ -15883,6 +16085,17 @@ react-remove-scroll-bar@^2.3.3:
|
||||||
react-style-singleton "^2.2.1"
|
react-style-singleton "^2.2.1"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
react-remove-scroll@2.5.5, react-remove-scroll@^2.5.5:
|
||||||
|
version "2.5.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77"
|
||||||
|
integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==
|
||||||
|
dependencies:
|
||||||
|
react-remove-scroll-bar "^2.3.3"
|
||||||
|
react-style-singleton "^2.2.1"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
use-callback-ref "^1.3.0"
|
||||||
|
use-sidecar "^1.1.2"
|
||||||
|
|
||||||
react-remove-scroll@^2.4.0:
|
react-remove-scroll@^2.4.0:
|
||||||
version "2.4.4"
|
version "2.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e"
|
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.4.tgz#2dfff377cf17efc00de39dad51c143fc7a1b9e3e"
|
||||||
|
@ -15894,17 +16107,6 @@ react-remove-scroll@^2.4.0:
|
||||||
use-callback-ref "^1.2.3"
|
use-callback-ref "^1.2.3"
|
||||||
use-sidecar "^1.0.1"
|
use-sidecar "^1.0.1"
|
||||||
|
|
||||||
react-remove-scroll@^2.5.5:
|
|
||||||
version "2.5.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77"
|
|
||||||
integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==
|
|
||||||
dependencies:
|
|
||||||
react-remove-scroll-bar "^2.3.3"
|
|
||||||
react-style-singleton "^2.2.1"
|
|
||||||
tslib "^2.1.0"
|
|
||||||
use-callback-ref "^1.3.0"
|
|
||||||
use-sidecar "^1.1.2"
|
|
||||||
|
|
||||||
react-router-dom@^6.3.0:
|
react-router-dom@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
|
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
|
||||||
|
|
Loading…
Reference in New Issue