|
| 1 | +import { Resource, core, dataBrowser, useStore } from '@tomic/react'; |
| 2 | +import { useState, useCallback, Suspense, lazy } from 'react'; |
| 3 | +import { FaPlus } from 'react-icons/fa'; |
| 4 | +import { randomItem } from '../../helpers/randomItem'; |
| 5 | +import { randomString } from '../../helpers/randomString'; |
| 6 | +import { stringToSlug } from '../../helpers/stringToSlug'; |
| 7 | +import { Button } from '../Button'; |
| 8 | +import { Row } from '../Row'; |
| 9 | +import { InputWrapper, InputStyled } from '../forms/InputStyles'; |
| 10 | +import { tagColours } from './tagColours'; |
| 11 | + |
| 12 | +const EmojiInput = lazy(() => import('../../chunks/EmojiInput/EmojiInput')); |
| 13 | + |
| 14 | +interface CreateTagRowProps { |
| 15 | + parent: string; |
| 16 | + onNewTag: (tag: Resource) => void; |
| 17 | +} |
| 18 | + |
| 19 | +export function CreateTagRow({ parent, onNewTag }: CreateTagRowProps) { |
| 20 | + const store = useStore(); |
| 21 | + const [tagName, setTagName] = useState<string>(''); |
| 22 | + const [emoji, setEmoji] = useState<string | undefined>(); |
| 23 | + const [resetKey, setResetKey] = useState<number>(0); |
| 24 | + |
| 25 | + const createNewTag = useCallback(async () => { |
| 26 | + const tag = await store.newResource({ |
| 27 | + subject: `${parent}/${randomString()}`, |
| 28 | + parent, |
| 29 | + isA: dataBrowser.classes.tag, |
| 30 | + propVals: { |
| 31 | + [core.properties.shortname]: tagName, |
| 32 | + [dataBrowser.properties.color]: randomItem(tagColours), |
| 33 | + }, |
| 34 | + }); |
| 35 | + |
| 36 | + if (emoji) { |
| 37 | + await tag.set(dataBrowser.properties.emoji, emoji, store); |
| 38 | + } |
| 39 | + |
| 40 | + onNewTag(tag); |
| 41 | + setTagName(''); |
| 42 | + setEmoji(undefined); |
| 43 | + setResetKey(prev => prev + 1); |
| 44 | + }, [parent, store, tagName, emoji, onNewTag]); |
| 45 | + |
| 46 | + const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { |
| 47 | + setTagName(stringToSlug(e.target.value)); |
| 48 | + }, []); |
| 49 | + |
| 50 | + const handleKeyDown = useCallback( |
| 51 | + (e: React.KeyboardEvent<HTMLInputElement>) => { |
| 52 | + if (e.key === 'Enter') { |
| 53 | + createNewTag(); |
| 54 | + } |
| 55 | + }, |
| 56 | + [createNewTag], |
| 57 | + ); |
| 58 | + |
| 59 | + return ( |
| 60 | + <Suspense fallback={<div>Loading...</div>}> |
| 61 | + <Row> |
| 62 | + <InputWrapper> |
| 63 | + <EmojiInput onChange={setEmoji} key={resetKey} /> |
| 64 | + <InputStyled |
| 65 | + placeholder='New tag' |
| 66 | + value={tagName} |
| 67 | + onChange={handleChange} |
| 68 | + onKeyDown={handleKeyDown} |
| 69 | + /> |
| 70 | + </InputWrapper> |
| 71 | + <Button title='Add tag' onClick={createNewTag} disabled={!tagName}> |
| 72 | + <FaPlus /> |
| 73 | + </Button> |
| 74 | + </Row> |
| 75 | + </Suspense> |
| 76 | + ); |
| 77 | +} |
0 commit comments