import Button from 'react-bootstrap/Button'
import InputGroup from 'react-bootstrap/InputGroup'
import BootstrapForm from 'react-bootstrap/Form'
import Alert from 'react-bootstrap/Alert'
import { Formik, Form as FormikForm, useFormikContext, useField } from 'formik'
import React, { useEffect, useRef, useState } from 'react'
import copy from 'clipboard-copy'
import Thumb from '../svgs/thumb-up-fill.svg'
import { Nav } from 'react-bootstrap'
import Markdown from '../svgs/markdown-line.svg'
import styles from './form.module.css'
import Text from '../components/text'
export function SubmitButton ({ children, variant, value, onClick, ...props }) {
const { isSubmitting, setFieldValue } = useFormikContext()
return (
)
}
export function CopyInput (props) {
const [copied, setCopied] = useState(false)
const handleClick = () => {
copy(props.placeholder)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}
return (
{copied ? : 'copy'}
}
{...props}
/>
)
}
export function InputSkeleton ({ label }) {
return (
{label && {label}}
)
}
export function MarkdownInput ({ label, groupClassName, ...props }) {
const [tab, setTab] = useState('write')
const [, meta] = useField(props)
useEffect(() => {
!meta.value && setTab('write')
}, [meta.value])
return (
)
}
function FormGroup ({ className, label, children }) {
return (
{label && {label}}
{children}
)
}
function InputInner ({
prepend, append, hint, showValid, onChange, overrideValue,
innerRef, storageKeyPrefix, ...props
}) {
const [field, meta, helpers] = props.readOnly ? [{}, {}, {}] : useField(props)
const formik = props.readOnly ? null : useFormikContext()
const storageKey = storageKeyPrefix ? storageKeyPrefix + '-' + props.name : undefined
useEffect(() => {
if (overrideValue) {
helpers.setValue(overrideValue)
if (storageKey) {
localStorage.setItem(storageKey, overrideValue)
}
} else if (storageKey) {
const draft = localStorage.getItem(storageKey)
if (draft) {
// for some reason we have to turn off validation to get formik to
// not assume this is invalid
helpers.setValue(draft, false)
}
}
}, [overrideValue])
return (
<>
{prepend && (
{prepend}
)}
{
if (e.keyCode === 13 && (e.metaKey || e.ctrlKey)) {
formik?.submitForm()
}
}}
ref={innerRef}
{...field} {...props}
onChange={(e) => {
field.onChange(e)
if (storageKey) {
localStorage.setItem(storageKey, e.target.value)
}
if (onChange) {
onChange(formik, e)
}
}}
isInvalid={meta.touched && meta.error}
isValid={showValid && meta.touched && !meta.error}
/>
{append && (
{append}
)}
{meta.touched && meta.error}
{hint && (
{hint}
)}
>
)
}
export function Input ({ label, groupClassName, ...props }) {
return (
)
}
export function Checkbox ({ children, label, extra, handleChange, inline, ...props }) {
// React treats radios and checkbox inputs differently other input types, select, and textarea.
// Formik does this too! When you specify `type` to useField(), it will
// return the correct bag of props for you
const [field] = useField({ ...props, type: 'checkbox' })
return (
{
field.onChange(e)
handleChange && handleChange(e.target.checked)
}}
/>
{label}
{extra &&
{extra}
}
)
}
export function Form ({
initial, schema, onSubmit, children, initialError, validateImmediately, storageKeyPrefix, ...props
}) {
const [error, setError] = useState(initialError)
return (
onSubmit && onSubmit(...args).then(() => {
if (!storageKeyPrefix) return
Object.keys(...args).forEach(v =>
localStorage.removeItem(storageKeyPrefix + '-' + v))
}).catch(e => setError(e.message || e))}
>
{error && setError(undefined)} dismissible>{error}}
{storageKeyPrefix
? React.Children.map(children, (child) => {
if (child) {
return React.cloneElement(child, {
storageKeyPrefix
})
}
})
: children}
)
}
export function SyncForm ({
initial, schema, children, action, ...props
}) {
const ref = useRef(null)
return (
ref.current.submit()}
>
{props => (
)}
)
}