Last active
September 20, 2019 19:19
-
-
Save mornir/d280a6c5e0eaf7ef2885aee9ef0a3c4e to your computer and use it in GitHub Desktop.
A Sanity custom input component for generating furigana from kanji
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import TextInput from 'part:@sanity/components/textinputs/default' | |
import FormField from 'part:@sanity/components/formfields/default' | |
import Button from 'part:@sanity/components/buttons/default' | |
import PropTypes from 'prop-types' | |
import ky from './ky' | |
const Furigana = require('gem-furigana').Furigana | |
import { | |
PatchEvent, | |
set, | |
setIfMissing, | |
unset, | |
} from 'part:@sanity/form-builder/patch-event' | |
export default class FuriganaInput extends React.Component { | |
static propTypes = { | |
value: PropTypes.string, | |
onChange: PropTypes.func.isRequired, | |
} | |
inputRef = React.createRef() | |
state = { | |
isGenerating: false, | |
displayedFurigana: { | |
__html: '', | |
}, | |
} | |
componentDidMount() { | |
this.setState({ | |
displayedFurigana: this.props.value | |
? this.displayFurigana(this.props.value) | |
: { __html: '' }, | |
}) | |
} | |
handleChange = event => { | |
const value = event.currentTarget.value | |
this.props.onChange(PatchEvent.from(value ? set(value) : unset())) | |
this.setState({ | |
displayedFurigana: this.displayFurigana(value), | |
}) | |
} | |
focus() { | |
if (this.inputRef) { | |
this.inputRef.current.focus() | |
} | |
} | |
displayFurigana = gemSyntax => { | |
const furigana = new Furigana(gemSyntax) | |
return { __html: furigana.ReadingHtml } | |
} | |
generateFurigana = async () => { | |
const value = this.props.value | |
if (!value || !value.trim()) return | |
this.setState({ isGenerating: true }) | |
try { | |
const furigana = await ky | |
.get('https://endpoint-for-generating-furigana/' + value.trim()) | |
.text() | |
const cleanFurigana = furigana.replace(/\[ \]\s?/g, '') | |
this.props.onChange(PatchEvent.from(set(cleanFurigana))) | |
this.setState({ | |
displayedFurigana: this.displayFurigana(cleanFurigana), | |
}) | |
} catch (e) { | |
console.log(e) | |
} finally { | |
this.setState({ isGenerating: false }) | |
} | |
} | |
render() { | |
const { value, type, markers, level, onFocus } = this.props | |
const validation = markers.filter(marker => marker.type === 'validation') | |
const errors = validation.filter(marker => marker.level === 'error') | |
const { isGenerating, displayedFurigana } = this.state | |
return ( | |
<React.Fragment> | |
<FormField | |
markers={markers} | |
level={level} | |
label={type.title} | |
description={type.description} | |
> | |
<div style={{ display: 'flex' }}> | |
<div style={{ flexGrow: 1 }}> | |
<TextInput | |
customValidity={errors.length > 0 ? errors[0].item.message : ''} | |
type="text" | |
value={value} | |
placeholder={type.placeholder} | |
onChange={this.handleChange} | |
onFocus={onFocus} | |
ref={this.inputRef} | |
/> | |
</div> | |
<Button | |
loading={isGenerating} | |
inverted | |
onClick={this.generateFurigana} | |
> | |
Get Furigana | |
</Button> | |
</div> | |
</FormField> | |
<p dangerouslySetInnerHTML={displayedFurigana} /> | |
</React.Fragment> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment