⚡ (embed) Add size and icon picker in bubble settings (#508)
This commit is contained in:
@@ -19,7 +19,7 @@ import tinyColor from 'tinycolor2'
|
||||
|
||||
const colorsSelection: `#${string}`[] = [
|
||||
'#666460',
|
||||
'#AFABA3',
|
||||
'#FFFFFF',
|
||||
'#A87964',
|
||||
'#D09C46',
|
||||
'#DE8031',
|
||||
@@ -27,7 +27,7 @@ const colorsSelection: `#${string}`[] = [
|
||||
'#4A8BB2',
|
||||
'#9B74B7',
|
||||
'#C75F96',
|
||||
'#C75F96',
|
||||
'#0042DA',
|
||||
]
|
||||
|
||||
type Props = {
|
||||
@@ -78,18 +78,19 @@ export const ColorPicker = ({ value, defaultValue, onColorChange }: Props) => {
|
||||
</PopoverHeader>
|
||||
<PopoverBody as={Stack}>
|
||||
<SimpleGrid columns={5} spacing={2}>
|
||||
{colorsSelection.map((c) => (
|
||||
{colorsSelection.map((color) => (
|
||||
<Button
|
||||
key={c}
|
||||
aria-label={c}
|
||||
background={c}
|
||||
key={color}
|
||||
aria-label={color}
|
||||
background={color}
|
||||
height="22px"
|
||||
width="22px"
|
||||
padding={0}
|
||||
minWidth="unset"
|
||||
borderRadius={3}
|
||||
_hover={{ background: c }}
|
||||
onClick={handleClick(c)}
|
||||
borderWidth={color === '#FFFFFF' ? 1 : undefined}
|
||||
_hover={{ background: color }}
|
||||
onClick={handleClick(color)}
|
||||
/>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
@@ -57,10 +57,9 @@ export const EditableEmojiOrImageIcon = ({
|
||||
filePath={uploadFilePath}
|
||||
defaultUrl={icon ?? ''}
|
||||
onSubmit={onChangeIcon}
|
||||
isGiphyEnabled={false}
|
||||
isUnsplashEnabled={false}
|
||||
isEmojiEnabled={true}
|
||||
excludedTabs={['giphy', 'unsplash']}
|
||||
onClose={onClose}
|
||||
initialTab="icon"
|
||||
/>
|
||||
</PopoverContent>
|
||||
</>
|
||||
|
||||
@@ -26,6 +26,13 @@ export const IconPicker = ({ onIconSelected }: Props) => {
|
||||
)
|
||||
const searchQuery = useRef<string>('')
|
||||
const [selectedColor, setSelectedColor] = useState(initialIconColor)
|
||||
const isWhite = useMemo(
|
||||
() =>
|
||||
selectedColor.toLowerCase() === '#ffffff' ||
|
||||
selectedColor.toLowerCase() === '#fff' ||
|
||||
selectedColor === 'white',
|
||||
[selectedColor]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!bottomElement.current) return
|
||||
@@ -68,10 +75,9 @@ export const IconPicker = ({ onIconSelected }: Props) => {
|
||||
|
||||
const selectIcon = async (iconName: string) => {
|
||||
const svg = await (await fetch(`/icons/${iconName}.svg`)).text()
|
||||
const dataUri = `data:image/svg+xml;utf8,${svg.replace(
|
||||
'<svg',
|
||||
`<svg fill='${encodeURIComponent(selectedColor)}'`
|
||||
)}`
|
||||
const dataUri = `data:image/svg+xml;utf8,${svg
|
||||
.replace('<svg', `<svg fill='${encodeURIComponent(selectedColor)}'`)
|
||||
.replace(/"/g, "'")}`
|
||||
onIconSelected(dataUri)
|
||||
}
|
||||
|
||||
@@ -96,8 +102,9 @@ export const IconPicker = ({ onIconSelected }: Props) => {
|
||||
>
|
||||
{displayedIconNames.map((iconName) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
variant={isWhite ? 'solid' : 'ghost'}
|
||||
colorScheme={isWhite ? 'blackAlpha' : undefined}
|
||||
fontSize="xl"
|
||||
w="38px"
|
||||
h="38px"
|
||||
|
||||
@@ -10,30 +10,52 @@ import { IconPicker } from './IconPicker'
|
||||
type Tabs = 'link' | 'upload' | 'giphy' | 'emoji' | 'unsplash' | 'icon'
|
||||
|
||||
type Props = {
|
||||
filePath: string
|
||||
filePath: string | undefined
|
||||
includeFileName?: boolean
|
||||
defaultUrl?: string
|
||||
isEmojiEnabled?: boolean
|
||||
isGiphyEnabled?: boolean
|
||||
isUnsplashEnabled?: boolean
|
||||
imageSize?: 'small' | 'regular' | 'thumb'
|
||||
initialTab?: Tabs
|
||||
onSubmit: (url: string) => void
|
||||
onClose?: () => void
|
||||
}
|
||||
} & (
|
||||
| {
|
||||
includedTabs?: Tabs[]
|
||||
}
|
||||
| {
|
||||
excludedTabs?: Tabs[]
|
||||
}
|
||||
)
|
||||
|
||||
const defaultDisplayedTabs: Tabs[] = [
|
||||
'link',
|
||||
'upload',
|
||||
'giphy',
|
||||
'emoji',
|
||||
'unsplash',
|
||||
'icon',
|
||||
]
|
||||
|
||||
export const ImageUploadContent = ({
|
||||
filePath,
|
||||
includeFileName,
|
||||
defaultUrl,
|
||||
onSubmit,
|
||||
isEmojiEnabled = false,
|
||||
isGiphyEnabled = true,
|
||||
isUnsplashEnabled = true,
|
||||
imageSize = 'regular',
|
||||
onClose,
|
||||
initialTab,
|
||||
...props
|
||||
}: Props) => {
|
||||
const includedTabs =
|
||||
'includedTabs' in props
|
||||
? props.includedTabs ?? defaultDisplayedTabs
|
||||
: defaultDisplayedTabs
|
||||
const excludedTabs = 'excludedTabs' in props ? props.excludedTabs ?? [] : []
|
||||
const displayedTabs = defaultDisplayedTabs.filter(
|
||||
(tab) => !excludedTabs.includes(tab) && includedTabs.includes(tab)
|
||||
)
|
||||
|
||||
const [currentTab, setCurrentTab] = useState<Tabs>(
|
||||
isEmojiEnabled ? 'emoji' : 'link'
|
||||
initialTab ?? displayedTabs[0]
|
||||
)
|
||||
|
||||
const handleSubmit = (url: string) => {
|
||||
@@ -44,7 +66,25 @@ export const ImageUploadContent = ({
|
||||
return (
|
||||
<Stack>
|
||||
<HStack>
|
||||
{isEmojiEnabled && (
|
||||
{displayedTabs.includes('link') && (
|
||||
<Button
|
||||
variant={currentTab === 'link' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('link')}
|
||||
size="sm"
|
||||
>
|
||||
Link
|
||||
</Button>
|
||||
)}
|
||||
{displayedTabs.includes('upload') && (
|
||||
<Button
|
||||
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('upload')}
|
||||
size="sm"
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
)}
|
||||
{displayedTabs.includes('emoji') && (
|
||||
<Button
|
||||
variant={currentTab === 'emoji' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('emoji')}
|
||||
@@ -53,21 +93,7 @@ export const ImageUploadContent = ({
|
||||
Emoji
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant={currentTab === 'link' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('link')}
|
||||
size="sm"
|
||||
>
|
||||
Link
|
||||
</Button>
|
||||
<Button
|
||||
variant={currentTab === 'upload' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('upload')}
|
||||
size="sm"
|
||||
>
|
||||
Upload
|
||||
</Button>
|
||||
{isGiphyEnabled && (
|
||||
{displayedTabs.includes('giphy') && (
|
||||
<Button
|
||||
variant={currentTab === 'giphy' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('giphy')}
|
||||
@@ -76,7 +102,7 @@ export const ImageUploadContent = ({
|
||||
Giphy
|
||||
</Button>
|
||||
)}
|
||||
{isUnsplashEnabled && (
|
||||
{displayedTabs.includes('unsplash') && (
|
||||
<Button
|
||||
variant={currentTab === 'unsplash' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('unsplash')}
|
||||
@@ -85,13 +111,15 @@ export const ImageUploadContent = ({
|
||||
Unsplash
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant={currentTab === 'icon' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('icon')}
|
||||
size="sm"
|
||||
>
|
||||
Icon
|
||||
</Button>
|
||||
{displayedTabs.includes('icon') && (
|
||||
<Button
|
||||
variant={currentTab === 'icon' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('icon')}
|
||||
size="sm"
|
||||
>
|
||||
Icon
|
||||
</Button>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<BodyContent
|
||||
@@ -115,14 +143,15 @@ const BodyContent = ({
|
||||
onSubmit,
|
||||
}: {
|
||||
includeFileName?: boolean
|
||||
filePath: string
|
||||
filePath: string | undefined
|
||||
tab: Tabs
|
||||
defaultUrl?: string
|
||||
imageSize: 'small' | 'regular' | 'thumb'
|
||||
onSubmit: (url: string) => void
|
||||
}) => {
|
||||
switch (tab) {
|
||||
case 'upload':
|
||||
case 'upload': {
|
||||
if (!filePath) return null
|
||||
return (
|
||||
<UploadFileContent
|
||||
filePath={filePath}
|
||||
@@ -130,6 +159,7 @@ const BodyContent = ({
|
||||
onNewUrl={onSubmit}
|
||||
/>
|
||||
)
|
||||
}
|
||||
case 'link':
|
||||
return <EmbedLinkContent defaultUrl={defaultUrl} onNewUrl={onSubmit} />
|
||||
case 'giphy':
|
||||
|
||||
Reference in New Issue
Block a user