カスタムフォーム

1import { Switch } from '@headlessui/react';
2import { EditorContent, useEditor } from '@tiptap/react';
3import StarterKit from '@tiptap/starter-kit';
4import React, { useEffect } from 'react';
5import {
6  Control,
7  Controller,
8  Noop,
9  useController,
10  useForm,
11} from 'react-hook-form';
12import Input from '../components/input';
13
14const FormWithUiLibrary = () => {
15  const { control, watch, register } = useForm({
16    defaultValues: {
17      term: false,
18      name: '',
19      body: 'xxx',
20    },
21  });
22
23  return (
24    <div className="grid grid-cols-1 lg:grid-cols-2">
25      <form className="space-y-6">
26        <div>
27          <h2>Headless UI</h2>
28          <Controller
29            name="term"
30            control={control}
31            render={({ field }) => (
32              <Switch
33                checked={field.value}
34                onBlur={field.onBlur}
35                onChange={field.onChange}
36                className={`${
37                  field.value ? 'bg-blue-600' : 'bg-gray-200'
38                } relative inline-flex items-center h-6 rounded-full w-11`}
39              >
40                <span className="sr-only">利用規約</span>
41                <span
42                  className={`${
43                    field.value ? 'translate-x-6' : 'translate-x-1'
44                  } inline-block w-4 h-4 transform bg-white rounded-full`}
45                />
46              </Switch>
47            )}
48          ></Controller>
49        </div>
50
51        <div>
52          <h2>カスタムコンポーネント</h2>
53          <Input type="text" autoComplete="off" {...register('name')} />
54        </div>
55
56        <div>
57          <h2>Tiptap</h2>
58          <Controller
59            name="body"
60            control={control}
61            render={({ field }) => (
62              <TiptapEditor
63                value={field.value}
64                onBlur={field.onBlur}
65                onChange={field.onChange}
66              />
67            )}
68          ></Controller>
69        </div>
70      </form>
71      <div>
72        <pre>{JSON.stringify(watch(), null, 2)}</pre>
73      </div>
74    </div>
75  );
76};
77
78export default FormWithUiLibrary;
79
80const TiptapEditor = ({
81  value,
82  onChange,
83  onBlur,
84}: {
85  value: string;
86  onChange: (data: string) => void;
87  onBlur: Noop;
88}) => {
89  const editor = useEditor({
90    extensions: [StarterKit],
91    onUpdate({ editor }) {
92      onChange(editor.isEmpty ? '' : editor.getHTML());
93    },
94    editorProps: {
95      attributes: {
96        class: 'p-2 rounded-md border border-gray-400',
97      },
98    },
99  });
100
101  useEffect(() => {
102    editor?.commands?.setContent(value);
103  }, [editor]);
104
105  return <EditorContent onBlur={onBlur} editor={editor} />;
106};

使用ライブラリ

なし

参考サイト

なし