form.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import React, { useEffect, useState } from 'react'
  2. import Button from '@/app/components/base/button'
  3. import Input from '@/app/components/base/input'
  4. import Textarea from '@/app/components/base/textarea'
  5. import { useChatContext } from '@/app/components/base/chat/chat/context'
  6. enum DATA_FORMAT {
  7. TEXT = 'text',
  8. JSON = 'json',
  9. }
  10. enum SUPPORTED_TAGS {
  11. LABEL = 'label',
  12. INPUT = 'input',
  13. TEXTAREA = 'textarea',
  14. BUTTON = 'button',
  15. }
  16. enum SUPPORTED_TYPES {
  17. TEXT = 'text',
  18. PASSWORD = 'password',
  19. EMAIL = 'email',
  20. NUMBER = 'number',
  21. }
  22. const MarkdownForm = ({ node }: any) => {
  23. // const supportedTypes = ['text', 'password', 'email', 'number']
  24. // <form data-format="text">
  25. // <label for="username">Username:</label>
  26. // <input type="text" name="username" />
  27. // <label for="password">Password:</label>
  28. // <input type="password" name="password" />
  29. // <label for="content">Content:</label>
  30. // <textarea name="content"></textarea>
  31. // <button data-size="small" data-variant="primary">Login</button>
  32. // </form>
  33. const { onSend } = useChatContext()
  34. const [formValues, setFormValues] = useState<{ [key: string]: any }>({})
  35. useEffect(() => {
  36. const initialValues: { [key: string]: any } = {}
  37. node.children.forEach((child: any) => {
  38. if ([SUPPORTED_TAGS.INPUT, SUPPORTED_TAGS.TEXTAREA].includes(child.tagName))
  39. initialValues[child.properties.name] = child.properties.value
  40. })
  41. setFormValues(initialValues)
  42. }, [node.children])
  43. const getFormValues = (children: any) => {
  44. const values: { [key: string]: any } = {}
  45. children.forEach((child: any) => {
  46. if ([SUPPORTED_TAGS.INPUT, SUPPORTED_TAGS.TEXTAREA].includes(child.tagName))
  47. values[child.properties.name] = formValues[child.properties.name]
  48. })
  49. return values
  50. }
  51. const onSubmit = (e: any) => {
  52. e.preventDefault()
  53. const format = node.properties.dataFormat || DATA_FORMAT.TEXT
  54. const result = getFormValues(node.children)
  55. if (format === DATA_FORMAT.JSON) {
  56. onSend?.(JSON.stringify(result))
  57. }
  58. else {
  59. const textResult = Object.entries(result)
  60. .map(([key, value]) => `${key}: ${value}`)
  61. .join('\n')
  62. onSend?.(textResult)
  63. }
  64. }
  65. return (
  66. <form
  67. autoComplete="off"
  68. className='flex flex-col self-stretch'
  69. onSubmit={(e: any) => {
  70. e.preventDefault()
  71. e.stopPropagation()
  72. }}
  73. >
  74. {node.children.filter((i: any) => i.type === 'element').map((child: any, index: number) => {
  75. if (child.tagName === SUPPORTED_TAGS.LABEL) {
  76. return (
  77. <label
  78. key={index}
  79. htmlFor={child.properties.for}
  80. className="my-2 system-md-semibold text-text-secondary"
  81. >
  82. {child.children[0]?.value || ''}
  83. </label>
  84. )
  85. }
  86. if (child.tagName === SUPPORTED_TAGS.INPUT && Object.values(SUPPORTED_TYPES).includes(child.properties.type)) {
  87. return (
  88. <Input
  89. key={index}
  90. type={child.properties.type}
  91. name={child.properties.name}
  92. placeholder={child.properties.placeholder}
  93. value={formValues[child.properties.name]}
  94. onChange={(e) => {
  95. setFormValues(prevValues => ({
  96. ...prevValues,
  97. [child.properties.name]: e.target.value,
  98. }))
  99. }}
  100. />
  101. )
  102. }
  103. if (child.tagName === SUPPORTED_TAGS.TEXTAREA) {
  104. return (
  105. <Textarea
  106. key={index}
  107. name={child.properties.name}
  108. placeholder={child.properties.placeholder}
  109. value={formValues[child.properties.name]}
  110. onChange={(e) => {
  111. setFormValues(prevValues => ({
  112. ...prevValues,
  113. [child.properties.name]: e.target.value,
  114. }))
  115. }}
  116. />
  117. )
  118. }
  119. if (child.tagName === SUPPORTED_TAGS.BUTTON) {
  120. const variant = child.properties.dataVariant
  121. const size = child.properties.dataSize
  122. return (
  123. <Button
  124. variant={variant}
  125. size={size}
  126. className='mt-4'
  127. key={index}
  128. onClick={onSubmit}
  129. >
  130. <span className='text-[13px]'>{child.children[0]?.value || ''}</span>
  131. </Button>
  132. )
  133. }
  134. return <p key={index}>Unsupported tag: {child.tagName}</p>
  135. })}
  136. </form>
  137. )
  138. }
  139. MarkdownForm.displayName = 'MarkdownForm'
  140. export default MarkdownForm