@dxos/react-ui-form 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +0 -1
  3. package/dist/lib/browser/index.mjs +4054 -2217
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/translations.mjs +87 -0
  7. package/dist/lib/browser/translations.mjs.map +7 -0
  8. package/dist/lib/node-esm/index.mjs +4054 -2217
  9. package/dist/lib/node-esm/index.mjs.map +4 -4
  10. package/dist/lib/node-esm/meta.json +1 -1
  11. package/dist/lib/node-esm/translations.mjs +89 -0
  12. package/dist/lib/node-esm/translations.mjs.map +7 -0
  13. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +8 -8
  14. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  15. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +89 -5
  16. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/Form.d.ts +135 -25
  18. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/Form.stories.d.ts +207 -56
  20. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/FormField.d.ts +52 -0
  22. package/dist/types/src/components/Form/FormField.d.ts.map +1 -0
  23. package/dist/types/src/components/Form/FormFieldComponent.d.ts +98 -0
  24. package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -0
  25. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts +9 -0
  26. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -0
  27. package/dist/types/src/components/Form/FormFieldSet.d.ts +26 -0
  28. package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -0
  29. package/dist/types/src/components/Form/FormTooltipsContext.d.ts +19 -0
  30. package/dist/types/src/components/Form/FormTooltipsContext.d.ts.map +1 -0
  31. package/dist/types/src/components/Form/Layout/FormLayout.d.ts +50 -0
  32. package/dist/types/src/components/Form/Layout/FormLayout.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts +123 -0
  34. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts +2 -0
  36. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts.map +1 -0
  37. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts +2 -0
  38. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts.map +1 -0
  39. package/dist/types/src/components/Form/Layout/annotation.d.ts +30 -0
  40. package/dist/types/src/components/Form/Layout/annotation.d.ts.map +1 -0
  41. package/dist/types/src/components/Form/Layout/index.d.ts +4 -0
  42. package/dist/types/src/components/Form/Layout/index.d.ts.map +1 -0
  43. package/dist/types/src/components/Form/Layout/parser.d.ts +31 -0
  44. package/dist/types/src/components/Form/Layout/parser.d.ts.map +1 -0
  45. package/dist/types/src/components/Form/Layout/parser.test.d.ts +2 -0
  46. package/dist/types/src/components/Form/Layout/parser.test.d.ts.map +1 -0
  47. package/dist/types/src/components/Form/fields/ArrayField.d.ts +18 -0
  48. package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -0
  49. package/dist/types/src/components/Form/fields/BooleanField.d.ts +4 -0
  50. package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -0
  51. package/dist/types/src/components/Form/fields/DateField.d.ts +4 -0
  52. package/dist/types/src/components/Form/fields/DateField.d.ts.map +1 -0
  53. package/dist/types/src/components/Form/fields/GeoPointField.d.ts +5 -0
  54. package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -0
  55. package/dist/types/src/components/Form/fields/InlineRefField.d.ts +13 -0
  56. package/dist/types/src/components/Form/fields/InlineRefField.d.ts.map +1 -0
  57. package/dist/types/src/components/Form/fields/MarkdownField.d.ts +11 -0
  58. package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -0
  59. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +89 -0
  60. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
  61. package/dist/types/src/components/Form/fields/NumberField.d.ts +4 -0
  62. package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -0
  63. package/dist/types/src/components/Form/fields/RefField.d.ts +34 -0
  64. package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -0
  65. package/dist/types/src/components/Form/fields/RefField.test.d.ts +2 -0
  66. package/dist/types/src/components/Form/fields/RefField.test.d.ts.map +1 -0
  67. package/dist/types/src/components/Form/fields/SelectField.d.ts +13 -0
  68. package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -0
  69. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +5 -0
  70. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -0
  71. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +89 -0
  72. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -0
  73. package/dist/types/src/components/Form/fields/TextAreaField.d.ts +4 -0
  74. package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -0
  75. package/dist/types/src/components/Form/fields/TextField.d.ts +4 -0
  76. package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -0
  77. package/dist/types/src/components/Form/fields/TupleField.d.ts +6 -0
  78. package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -0
  79. package/dist/types/src/components/Form/fields/index.d.ts +14 -0
  80. package/dist/types/src/components/Form/fields/index.d.ts.map +1 -0
  81. package/dist/types/src/components/Form/index.d.ts +5 -4
  82. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  83. package/dist/types/src/components/Form/meta-tags.d.ts +30 -0
  84. package/dist/types/src/components/Form/meta-tags.d.ts.map +1 -0
  85. package/dist/types/src/components/Form/meta-tags.test.d.ts +2 -0
  86. package/dist/types/src/components/Form/meta-tags.test.d.ts.map +1 -0
  87. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +8 -0
  88. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
  89. package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts +87 -0
  90. package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts.map +1 -0
  91. package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
  92. package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
  93. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +68 -0
  94. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
  95. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +92 -0
  96. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
  97. package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
  98. package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
  99. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
  100. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
  101. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +132 -0
  102. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
  103. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
  104. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
  105. package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
  106. package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
  107. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts +9 -0
  108. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts.map +1 -0
  109. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts +91 -0
  110. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/ObjectTree/index.d.ts +2 -0
  112. package/dist/types/src/components/ObjectTree/index.d.ts.map +1 -0
  113. package/dist/types/src/components/RefEditor/RefEditor.d.ts +73 -0
  114. package/dist/types/src/components/RefEditor/RefEditor.d.ts.map +1 -0
  115. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts +92 -0
  116. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts.map +1 -0
  117. package/dist/types/src/components/RefEditor/index.d.ts +3 -0
  118. package/dist/types/src/components/RefEditor/index.d.ts.map +1 -0
  119. package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts +47 -0
  120. package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts.map +1 -0
  121. package/dist/types/src/components/Settings/Settings.d.ts +51 -0
  122. package/dist/types/src/components/Settings/Settings.d.ts.map +1 -0
  123. package/dist/types/src/components/Settings/Settings.stories.d.ts +89 -0
  124. package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -0
  125. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
  126. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
  127. package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
  128. package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
  129. package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
  130. package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
  131. package/dist/types/src/components/Settings/index.d.ts +4 -0
  132. package/dist/types/src/components/Settings/index.d.ts.map +1 -0
  133. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +21 -11
  134. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  135. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +91 -9
  136. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  137. package/dist/types/src/components/index.d.ts +6 -2
  138. package/dist/types/src/components/index.d.ts.map +1 -1
  139. package/dist/types/src/components/testing.d.ts +14 -4
  140. package/dist/types/src/components/testing.d.ts.map +1 -1
  141. package/dist/types/src/hooks/index.d.ts +2 -3
  142. package/dist/types/src/hooks/index.d.ts.map +1 -1
  143. package/dist/types/src/hooks/useFormHandler.d.ts +82 -0
  144. package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -0
  145. package/dist/types/src/hooks/useKeyHandler.d.ts +7 -0
  146. package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -0
  147. package/dist/types/src/index.d.ts +0 -2
  148. package/dist/types/src/index.d.ts.map +1 -1
  149. package/dist/types/src/translations.d.ts +70 -55
  150. package/dist/types/src/translations.d.ts.map +1 -1
  151. package/dist/types/src/util/field-type.d.ts +19 -0
  152. package/dist/types/src/util/field-type.d.ts.map +1 -0
  153. package/dist/types/src/util/field.d.ts +3 -3
  154. package/dist/types/src/util/field.d.ts.map +1 -1
  155. package/dist/types/src/util/formatting.d.ts +2 -2
  156. package/dist/types/src/util/formatting.d.ts.map +1 -1
  157. package/dist/types/src/util/index.d.ts +2 -1
  158. package/dist/types/src/util/index.d.ts.map +1 -1
  159. package/dist/types/src/util/properties.d.ts +35 -0
  160. package/dist/types/src/util/properties.d.ts.map +1 -0
  161. package/dist/types/src/util/properties.test.d.ts +2 -0
  162. package/dist/types/src/util/properties.test.d.ts.map +1 -0
  163. package/dist/types/src/util/refs.d.ts +3 -3
  164. package/dist/types/src/util/refs.d.ts.map +1 -1
  165. package/dist/types/tsconfig.tsbuildinfo +1 -1
  166. package/package.json +64 -47
  167. package/src/components/FieldEditor/FieldEditor.stories.tsx +49 -31
  168. package/src/components/FieldEditor/FieldEditor.test.tsx +4 -2
  169. package/src/components/FieldEditor/FieldEditor.tsx +100 -97
  170. package/src/components/Form/AUDIT.md +17 -0
  171. package/src/components/Form/Form.stories.tsx +151 -221
  172. package/src/components/Form/Form.tsx +461 -95
  173. package/src/components/Form/FormField.tsx +345 -0
  174. package/src/components/Form/FormFieldComponent.stories.tsx +65 -0
  175. package/src/components/Form/FormFieldComponent.tsx +253 -0
  176. package/src/components/Form/FormFieldSet.tsx +213 -0
  177. package/src/components/Form/FormTooltipsContext.ts +25 -0
  178. package/src/components/Form/Layout/FormLayout.stories.test.tsx +51 -0
  179. package/src/components/Form/Layout/FormLayout.stories.tsx +422 -0
  180. package/src/components/Form/Layout/FormLayout.test.ts +59 -0
  181. package/src/components/Form/Layout/FormLayout.tsx +251 -0
  182. package/src/components/Form/Layout/annotation.ts +38 -0
  183. package/src/components/Form/Layout/index.ts +7 -0
  184. package/src/components/Form/Layout/parser.test.ts +120 -0
  185. package/src/components/Form/Layout/parser.ts +167 -0
  186. package/src/components/Form/README.md +3 -0
  187. package/src/components/Form/fields/ArrayField.tsx +173 -0
  188. package/src/components/Form/fields/BooleanField.tsx +22 -0
  189. package/src/components/Form/fields/DateField.tsx +101 -0
  190. package/src/components/Form/fields/GeoPointField.tsx +124 -0
  191. package/src/components/Form/fields/InlineRefField.tsx +138 -0
  192. package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
  193. package/src/components/Form/fields/MarkdownField.tsx +167 -0
  194. package/src/components/Form/fields/NumberField.tsx +76 -0
  195. package/src/components/Form/fields/RefField.test.ts +45 -0
  196. package/src/components/Form/fields/RefField.tsx +266 -0
  197. package/src/components/Form/fields/SelectField.tsx +77 -0
  198. package/src/components/Form/fields/SelectOptionField.stories.tsx +66 -0
  199. package/src/components/Form/{custom/SelectOptionsInput.tsx → fields/SelectOptionField.tsx} +39 -32
  200. package/src/components/Form/fields/TextAreaField.tsx +38 -0
  201. package/src/components/Form/fields/TextField.tsx +38 -0
  202. package/src/components/Form/fields/TupleField.tsx +55 -0
  203. package/src/components/Form/fields/index.ts +17 -0
  204. package/src/components/Form/index.ts +6 -4
  205. package/src/components/Form/meta-tags.test.ts +47 -0
  206. package/src/components/Form/meta-tags.ts +33 -0
  207. package/src/components/ObjectForm/ObjectForm.stories.tsx +62 -0
  208. package/src/components/ObjectForm/ObjectForm.tsx +111 -0
  209. package/src/components/{ControlSection → ObjectForm}/index.ts +1 -1
  210. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +212 -0
  211. package/src/components/ObjectPicker/ObjectPicker.tsx +202 -0
  212. package/src/components/ObjectPicker/index.ts +5 -0
  213. package/src/components/ObjectProperties/ObjectProperties.stories.tsx +350 -0
  214. package/src/components/ObjectProperties/ObjectProperties.test.tsx +111 -0
  215. package/src/components/ObjectProperties/ObjectProperties.tsx +146 -0
  216. package/src/components/ObjectProperties/index.ts +5 -0
  217. package/src/components/ObjectTree/ObjectTree.stories.tsx +134 -0
  218. package/src/components/ObjectTree/ObjectTree.tsx +190 -0
  219. package/src/components/ObjectTree/index.ts +5 -0
  220. package/src/components/RefEditor/RefEditor.stories.tsx +148 -0
  221. package/src/components/RefEditor/RefEditor.tsx +275 -0
  222. package/src/components/RefEditor/index.ts +6 -0
  223. package/src/components/RefEditor/ref-editor-extension.ts +254 -0
  224. package/src/components/Settings/AUDIT.md +51 -0
  225. package/src/components/Settings/Settings.stories.tsx +104 -0
  226. package/src/components/Settings/Settings.tsx +81 -0
  227. package/src/components/Settings/SettingsFieldSet.tsx +257 -0
  228. package/src/components/Settings/SettingsItem.tsx +58 -0
  229. package/src/components/Settings/SettingsSelectField.tsx +59 -0
  230. package/src/components/Settings/index.ts +7 -0
  231. package/src/components/ViewEditor/ViewEditor.stories.tsx +132 -64
  232. package/src/components/ViewEditor/ViewEditor.test.tsx +23 -22
  233. package/src/components/ViewEditor/ViewEditor.tsx +378 -216
  234. package/src/components/index.ts +6 -3
  235. package/src/components/testing.tsx +31 -12
  236. package/src/hooks/index.ts +2 -3
  237. package/src/hooks/useFormHandler.ts +380 -0
  238. package/src/hooks/useKeyHandler.tsx +37 -0
  239. package/src/index.ts +0 -4
  240. package/src/translations.ts +76 -59
  241. package/src/util/field-type.ts +60 -0
  242. package/src/util/field.ts +33 -43
  243. package/src/util/formatting.ts +22 -22
  244. package/src/util/index.ts +2 -1
  245. package/src/util/properties.test.ts +153 -0
  246. package/src/util/properties.ts +100 -0
  247. package/src/util/refs.ts +20 -19
  248. package/src/vite-env.d.ts +10 -0
  249. package/dist/types/src/components/ControlSection/ControlSection.d.ts +0 -23
  250. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +0 -1
  251. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +0 -8
  252. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +0 -1
  253. package/dist/types/src/components/ControlSection/index.d.ts +0 -2
  254. package/dist/types/src/components/ControlSection/index.d.ts.map +0 -1
  255. package/dist/types/src/components/Form/ArrayField.d.ts +0 -16
  256. package/dist/types/src/components/Form/ArrayField.d.ts.map +0 -1
  257. package/dist/types/src/components/Form/Defaults.d.ts +0 -14
  258. package/dist/types/src/components/Form/Defaults.d.ts.map +0 -1
  259. package/dist/types/src/components/Form/FormActions.d.ts +0 -9
  260. package/dist/types/src/components/Form/FormActions.d.ts.map +0 -1
  261. package/dist/types/src/components/Form/FormContent.d.ts +0 -57
  262. package/dist/types/src/components/Form/FormContent.d.ts.map +0 -1
  263. package/dist/types/src/components/Form/FormContext.d.ts +0 -23
  264. package/dist/types/src/components/Form/FormContext.d.ts.map +0 -1
  265. package/dist/types/src/components/Form/Input.d.ts +0 -26
  266. package/dist/types/src/components/Form/Input.d.ts.map +0 -1
  267. package/dist/types/src/components/Form/RefField.d.ts +0 -12
  268. package/dist/types/src/components/Form/RefField.d.ts.map +0 -1
  269. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +0 -4
  270. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +0 -1
  271. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +0 -4
  272. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +0 -1
  273. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +0 -7
  274. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +0 -1
  275. package/dist/types/src/components/Form/custom/TupleInput.d.ts +0 -6
  276. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +0 -1
  277. package/dist/types/src/components/Form/custom/index.d.ts +0 -4
  278. package/dist/types/src/components/Form/custom/index.d.ts.map +0 -1
  279. package/dist/types/src/components/Form/factory.d.ts +0 -8
  280. package/dist/types/src/components/Form/factory.d.ts.map +0 -1
  281. package/dist/types/src/components/deprecated/Form.d.ts +0 -15
  282. package/dist/types/src/components/deprecated/Form.d.ts.map +0 -1
  283. package/dist/types/src/components/deprecated/Form.stories.d.ts +0 -13
  284. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +0 -1
  285. package/dist/types/src/components/deprecated/FormInput.d.ts +0 -16
  286. package/dist/types/src/components/deprecated/FormInput.d.ts.map +0 -1
  287. package/dist/types/src/components/deprecated/index.d.ts +0 -2
  288. package/dist/types/src/components/deprecated/index.d.ts.map +0 -1
  289. package/dist/types/src/hooks/useForm.d.ts +0 -67
  290. package/dist/types/src/hooks/useForm.d.ts.map +0 -1
  291. package/dist/types/src/hooks/useQueryRefOptions.d.ts +0 -23
  292. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +0 -1
  293. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +0 -8
  294. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +0 -1
  295. package/dist/types/src/util/schema.d.ts +0 -3
  296. package/dist/types/src/util/schema.d.ts.map +0 -1
  297. package/src/components/ControlSection/ControlSection.stories.tsx +0 -42
  298. package/src/components/ControlSection/ControlSection.tsx +0 -139
  299. package/src/components/Form/ArrayField.tsx +0 -125
  300. package/src/components/Form/Defaults.tsx +0 -204
  301. package/src/components/Form/FormActions.tsx +0 -54
  302. package/src/components/Form/FormContent.tsx +0 -241
  303. package/src/components/Form/FormContext.tsx +0 -110
  304. package/src/components/Form/Input.tsx +0 -51
  305. package/src/components/Form/RefField.tsx +0 -214
  306. package/src/components/Form/custom/GeoPointInput.tsx +0 -72
  307. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +0 -62
  308. package/src/components/Form/custom/TupleInput.tsx +0 -47
  309. package/src/components/Form/custom/index.ts +0 -7
  310. package/src/components/Form/factory.tsx +0 -31
  311. package/src/components/deprecated/Form.stories.tsx +0 -63
  312. package/src/components/deprecated/Form.tsx +0 -119
  313. package/src/components/deprecated/FormInput.tsx +0 -71
  314. package/src/components/deprecated/index.ts +0 -5
  315. package/src/hooks/useForm.ts +0 -293
  316. package/src/hooks/useQueryRefOptions.ts +0 -53
  317. package/src/hooks/useRefQueryLookupHandler.ts +0 -39
  318. package/src/util/schema.ts +0 -14
@@ -0,0 +1,345 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Match from 'effect/Match';
6
+ import * as Option from 'effect/Option';
7
+ import * as Schema from 'effect/Schema';
8
+ import * as SchemaAST from 'effect/SchemaAST';
9
+ import * as String from 'effect/String';
10
+ import React, { useMemo } from 'react';
11
+
12
+ import { Annotation, Format } from '@dxos/echo';
13
+ import { SchemaEx } from '@dxos/effect';
14
+ import { IconButton, IconButtonProps, useTranslation } from '@dxos/react-ui';
15
+ import { type ProjectionModel } from '@dxos/schema';
16
+ import { mx } from '@dxos/ui-theme';
17
+
18
+ import { translationKey } from '#translations';
19
+
20
+ import { getRefProps } from '../../util';
21
+ import {
22
+ ArrayField,
23
+ BooleanField,
24
+ DateField,
25
+ GeoPointField,
26
+ InlineRefField,
27
+ MarkdownField,
28
+ NumberField,
29
+ RefField,
30
+ type RefFieldProps,
31
+ SelectField,
32
+ TextAreaField,
33
+ TextField,
34
+ } from './fields';
35
+ import { useFormFieldState } from './Form';
36
+ import {
37
+ type FormFieldComponent,
38
+ type FormFieldComponentProps,
39
+ type FormFieldMap,
40
+ type FormFieldProvider,
41
+ } from './FormFieldComponent';
42
+ import { FormFieldSet } from './FormFieldSet';
43
+
44
+ export type FormFieldProps = {
45
+ /**
46
+ * AST of the property to render.
47
+ */
48
+ type: SchemaAST.AST;
49
+
50
+ /**
51
+ * Name of the property. Used to derive a default label
52
+ * (`title ?? capitalize(name)`) and as the projection lookup key. Pass
53
+ * `null` to suppress the header label entirely -- the form still renders
54
+ * the field/struct, but `FormFieldSet`'s top-level `<FormFieldLabel>` is
55
+ * skipped. Used by `ArrayField` for object-array items, where every item
56
+ * would otherwise repeat the array's parent name.
57
+ */
58
+ name: string | null;
59
+
60
+ /**
61
+ * Path to the current object from the root. Used with nested forms.
62
+ */
63
+ path?: (string | number)[];
64
+
65
+ /**
66
+ * Optional projection for projection-based field management.
67
+ */
68
+ projection?: ProjectionModel;
69
+
70
+ /**
71
+ * Map of custom renderers for specific properties.
72
+ * Prefer fieldProvider for plugin specific input surfaces.
73
+ */
74
+ fieldMap?: FormFieldMap;
75
+
76
+ /**
77
+ * Function to lookup custom renderers for specific properties.
78
+ */
79
+ fieldProvider?: FormFieldProvider;
80
+
81
+ /**
82
+ * Typename of the ref type that the create props apply to.
83
+ * When set, createOptionLabel/createOptionIcon/createInitialValuePath/createFieldMap/onCreate
84
+ * are only passed to ref fields whose typename matches.
85
+ */
86
+ createTypename?: string;
87
+ } & Pick<FormFieldComponentProps, 'autoFocus' | 'readonly' | 'layout'> &
88
+ Pick<
89
+ RefFieldProps,
90
+ | 'createOptionLabel'
91
+ | 'createOptionIcon'
92
+ | 'createInitialValuePath'
93
+ | 'createFieldMap'
94
+ | 'db'
95
+ | 'useType'
96
+ | 'getOptions'
97
+ | 'onCreate'
98
+ >;
99
+
100
+ export const FormField = (props: FormFieldProps) => {
101
+ const {
102
+ type,
103
+ name,
104
+ path,
105
+ projection,
106
+ fieldMap,
107
+ fieldProvider,
108
+ readonly,
109
+ layout,
110
+
111
+ // RefFieldProps
112
+ createTypename,
113
+ createOptionLabel,
114
+ createOptionIcon,
115
+ createInitialValuePath,
116
+ createFieldMap,
117
+ db,
118
+ useType: schemaHook,
119
+ getOptions,
120
+ onCreate,
121
+ } = props;
122
+ const { t } = useTranslation(translationKey);
123
+ const title = SchemaEx.getAnnotation<string>(SchemaAST.TitleAnnotationId)(type);
124
+ const description = SchemaEx.getAnnotation<string>(SchemaAST.DescriptionAnnotationId)(type);
125
+ const examples = SchemaEx.getAnnotation<string[]>(SchemaAST.ExamplesAnnotationId)(type);
126
+
127
+ // `name === null` means "no header" -- collapse to an empty string so
128
+ // downstream consumers keep their `label: string` types, and the falsy
129
+ // value lets `FormFieldSet`'s `label && <FormFieldLabel ...>` guard skip
130
+ // the header.
131
+ const label = useMemo(() => title ?? (name == null ? '' : String.capitalize(name)), [title, name]);
132
+ const placeholder = useMemo(
133
+ () => (examples?.length ? `${t('example.placeholder')}: ${examples[0]}` : (description ?? label)),
134
+ [examples, description, label],
135
+ );
136
+
137
+ const fieldState = useFormFieldState(FormField.displayName, path);
138
+ const jsonPath = SchemaEx.createJsonPath(path ?? []);
139
+ const fieldProps: FormFieldComponentProps = {
140
+ type,
141
+ format: Format.FormatAnnotation.getFromAst(type).pipe((annotation) => Option.getOrUndefined(annotation)),
142
+ readonly,
143
+ label,
144
+ jsonPath,
145
+ placeholder,
146
+ layout,
147
+ db,
148
+ ...fieldState,
149
+ };
150
+
151
+ // Omit empty fields entirely in read-only mode -- an empty value has nothing
152
+ // to display, so a labelled row with a blank input is just noise. This
153
+ // mirrors what `FormFieldWrapper` already does for `layout === 'static'`, but
154
+ // covers every field type (including those that bypass the wrapper:
155
+ // RefField, SelectField, MarkdownField, ...). Container fields
156
+ // (`ArrayField`, nested-struct -> `FormFieldSet`) keep their own
157
+ // empty-value checks, but those branches only apply when the value is
158
+ // actually a non-null array/object, so this check doesn't interfere.
159
+ if (readonly && fieldState.getValue() == null) {
160
+ return null;
161
+ }
162
+
163
+ //
164
+ // Custom field.
165
+ //
166
+
167
+ const CustomField = fieldMap?.[jsonPath];
168
+ if (CustomField) {
169
+ return <CustomField {...fieldProps} />;
170
+ }
171
+
172
+ // TODO(burdon): Expensive to create schema each time; pass AST?
173
+ const component = fieldProvider?.({ schema: Schema.make(type), prop: name ?? '', fieldProps });
174
+ if (component) {
175
+ return component;
176
+ }
177
+
178
+ //
179
+ // Array field.
180
+ //
181
+
182
+ if (SchemaEx.isArrayType(type)) {
183
+ return <ArrayField fieldProps={fieldState} label={label} {...props} />;
184
+ }
185
+
186
+ //
187
+ // Regular field.
188
+ //
189
+
190
+ const Field = getFormField(fieldProps);
191
+ if (Field) {
192
+ return <Field {...fieldProps} />;
193
+ }
194
+
195
+ //
196
+ // Select field.
197
+ //
198
+
199
+ const options = getSelectOptions(type);
200
+ if (options) {
201
+ // Resolve labels from projection metadata when available.
202
+ const fieldProjections = projection?.getFieldProjections();
203
+ const fieldProjection = fieldProjections?.find((fp) => fp.field.path === name);
204
+ const selectOptions = fieldProjection?.props.options;
205
+
206
+ return (
207
+ <SelectField
208
+ {...fieldProps}
209
+ options={options.map((option) => {
210
+ const selectOption = selectOptions?.find((so) => so.id === globalThis.String(option));
211
+ return {
212
+ value: option,
213
+ label: selectOption?.title ?? option.toString(),
214
+ };
215
+ })}
216
+ />
217
+ );
218
+ }
219
+
220
+ //
221
+ // Ref field.
222
+ //
223
+
224
+ const refProps = getRefProps(type);
225
+ if (refProps) {
226
+ // Inline a single referenced object's own fields (nested form) instead of a picker.
227
+ const inline = Annotation.FormInlineAnnotation.getFromAst(refProps.ast).pipe(Option.getOrElse(() => false));
228
+ if (inline && !refProps.isArray) {
229
+ return <InlineRefField {...fieldProps} {...refProps} db={db} useType={schemaHook} onCreate={onCreate} />;
230
+ }
231
+
232
+ const isCreateTarget = !createTypename || refProps.typename === createTypename;
233
+ return (
234
+ <RefField
235
+ {...fieldProps}
236
+ {...refProps}
237
+ createOptionLabel={isCreateTarget ? createOptionLabel : undefined}
238
+ createOptionIcon={isCreateTarget ? createOptionIcon : undefined}
239
+ createInitialValuePath={isCreateTarget ? createInitialValuePath : undefined}
240
+ createFieldMap={isCreateTarget ? createFieldMap : undefined}
241
+ db={db}
242
+ useType={schemaHook}
243
+ getOptions={getOptions}
244
+ onCreate={onCreate}
245
+ />
246
+ );
247
+ }
248
+
249
+ //
250
+ // Nested Object field.
251
+ //
252
+
253
+ if (SchemaEx.isNestedType(type)) {
254
+ const baseNode = SchemaEx.findNode(type, SchemaEx.isDiscriminatedUnion);
255
+ const typeLiteral = baseNode
256
+ ? SchemaEx.getDiscriminatedType(baseNode, fieldState.getValue() as any)
257
+ : SchemaEx.findNode(type, SchemaAST.isTypeLiteral);
258
+
259
+ if (typeLiteral) {
260
+ const schema = Schema.make(typeLiteral);
261
+ return (
262
+ <FormFieldSet
263
+ schema={schema}
264
+ path={path}
265
+ readonly={readonly}
266
+ layout={layout}
267
+ label={label}
268
+ collapsible
269
+ projection={projection}
270
+ fieldMap={fieldMap}
271
+ fieldProvider={fieldProvider}
272
+ createOptionLabel={createOptionLabel}
273
+ createOptionIcon={createOptionIcon}
274
+ createInitialValuePath={createInitialValuePath}
275
+ db={db}
276
+ useType={schemaHook}
277
+ getOptions={getOptions}
278
+ onCreate={onCreate}
279
+ />
280
+ );
281
+ }
282
+ }
283
+
284
+ return null;
285
+ };
286
+
287
+ FormField.displayName = 'Form.FormField';
288
+
289
+ //
290
+ // Layout components
291
+ //
292
+
293
+ export const IconBlock = ({ inline, ...props }: IconButtonProps & { inline?: boolean }) => {
294
+ return (
295
+ <div className={mx('h-full flex px-1', inline ? 'items-center' : 'flex-col pt-2.5')}>
296
+ <IconButton variant='ghost' density='xs' square iconOnly {...props} />
297
+ </div>
298
+ );
299
+ };
300
+
301
+ /**
302
+ * Get property input component.
303
+ */
304
+ const getFormField = ({ type, format }: FormFieldComponentProps): FormFieldComponent | undefined => {
305
+ //
306
+ // Standard formats.
307
+ //
308
+
309
+ const formatField = Match.value(format).pipe(
310
+ Match.withReturnType<FormFieldComponent | undefined>(),
311
+ Match.when(Format.TypeFormat.Date, () => DateField),
312
+ Match.when(Format.TypeFormat.DateTime, () => DateField),
313
+ Match.when(Format.TypeFormat.GeoPoint, () => GeoPointField),
314
+ Match.when(Format.TypeFormat.Markdown, () => MarkdownField),
315
+ Match.when(Format.TypeFormat.Text, () => TextAreaField),
316
+ Match.when(Format.TypeFormat.Time, () => DateField),
317
+ Match.orElse(() => undefined),
318
+ );
319
+ if (formatField) {
320
+ return formatField;
321
+ }
322
+
323
+ //
324
+ // Standard types.
325
+ //
326
+
327
+ switch (type._tag) {
328
+ // TODO(wittjosiah): Schema.Any is currently used to represent template inputs.
329
+ case 'AnyKeyword':
330
+ case 'StringKeyword':
331
+ return TextField;
332
+ case 'NumberKeyword':
333
+ return NumberField;
334
+ case 'BooleanKeyword':
335
+ return BooleanField;
336
+ }
337
+ };
338
+
339
+ const getSelectOptions = (ast: SchemaAST.AST): Format.Options[] | undefined => {
340
+ if (SchemaEx.isLiteralUnion(ast)) {
341
+ return ast.types.map((type) => type.literal).filter((v): v is string | number => v !== null);
342
+ }
343
+
344
+ return Format.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option.getOrUndefined(annotation));
345
+ };
@@ -0,0 +1,65 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { type ChangeEvent, useCallback } from 'react';
7
+
8
+ import { Input } from '@dxos/react-ui';
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { type FormFieldComponentProps, FormFieldWrapper } from './FormFieldComponent';
12
+
13
+ const DefaultStory = ({
14
+ type,
15
+ placeholder,
16
+ readonly,
17
+ onBlur,
18
+ onValueChange,
19
+ ...props
20
+ }: FormFieldComponentProps<string>) => {
21
+ const handleChange = useCallback(
22
+ (event: ChangeEvent<HTMLInputElement>) => onValueChange(type, event.target.value),
23
+ [type, onValueChange],
24
+ );
25
+
26
+ return (
27
+ <div className='p-form-padding'>
28
+ <FormFieldWrapper<string> {...props}>
29
+ {({ value = '' }) => (
30
+ <Input.TextInput
31
+ disabled={!!readonly}
32
+ placeholder={placeholder}
33
+ noAutoFill
34
+ value={value}
35
+ onChange={handleChange}
36
+ onBlur={onBlur}
37
+ />
38
+ )}
39
+ </FormFieldWrapper>
40
+ </div>
41
+ );
42
+ };
43
+
44
+ const meta: Meta<typeof DefaultStory> = {
45
+ title: 'ui/react-ui-form/FormFieldComponent',
46
+ component: DefaultStory,
47
+ decorators: [withTheme(), withLayout({ layout: 'column' })],
48
+ parameters: {
49
+ layout: 'fullscreen',
50
+ },
51
+ };
52
+
53
+ export default meta;
54
+
55
+ type Story = StoryObj<typeof meta>;
56
+
57
+ export const Default: Story = {
58
+ args: {
59
+ label: 'Label',
60
+ getStatus: () => ({ status: 'error', error: 'Required field' }),
61
+ getValue: () => 'DXOS',
62
+ onBlur: () => {},
63
+ onValueChange: () => {},
64
+ },
65
+ };
@@ -0,0 +1,253 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { format as formatDate } from 'date-fns';
6
+ import type * as Schema from 'effect/Schema';
7
+ import type * as SchemaAST from 'effect/SchemaAST';
8
+ import React, {
9
+ Component,
10
+ type FC,
11
+ type FocusEvent,
12
+ type PropsWithChildren,
13
+ type ReactElement,
14
+ type ReactNode,
15
+ } from 'react';
16
+
17
+ import { type Database, Format } from '@dxos/echo';
18
+ import { Icon, Input, ThemedClassName, Tooltip } from '@dxos/react-ui';
19
+ import { inputTextLabel } from '@dxos/react-ui';
20
+ import { mx } from '@dxos/ui-theme';
21
+
22
+ import { type FormFieldStatus } from '../../hooks';
23
+ import { useFormTooltips } from './FormTooltipsContext';
24
+
25
+ /**
26
+ * Dynamic props passed to input components.
27
+ */
28
+ export type FormFieldStateProps<T = any> = {
29
+ getStatus: () => FormFieldStatus;
30
+ getValue: () => T | undefined;
31
+ onBlur: (event: FocusEvent<HTMLElement>) => void;
32
+ onValueChange: (type: SchemaAST.AST, value: T) => void;
33
+ };
34
+
35
+ /**
36
+ * Presentation mode.
37
+ * - full: Show label, control, and status.
38
+ * - compact: Show label and control.
39
+ * - inline: Control only.
40
+ * - static: Plain DOM; omit all undefined values.
41
+ */
42
+ // TODO(burdon): 'inline' should be orthogonal to the layout (e.g., array of inline static).
43
+ export type Presentation = 'full' | 'compact' | 'inline' | 'static';
44
+
45
+ /**
46
+ * Props passed to input components.
47
+ */
48
+ export type FormFieldComponentProps<T = any> = {
49
+ /** Database the form is editing against; populated for fields whose value is an ECHO object/Ref. */
50
+ db?: Database.Database;
51
+ type: SchemaAST.AST;
52
+ format?: Format.TypeFormat;
53
+ readonly?: boolean;
54
+ label: string;
55
+ /**
56
+ * Dotted JSON path of this field within the form values (e.g.
57
+ * `runtime.client.storage.persistent`). Forwarded to `FormFieldLabel` so
58
+ * that it can render the path as a debug hint when the enclosing
59
+ * `Form.Root` has `debug` enabled.
60
+ */
61
+ jsonPath?: string;
62
+ placeholder?: string;
63
+ autoFocus?: boolean;
64
+ layout?: Presentation;
65
+ } & FormFieldStateProps<T>;
66
+
67
+ export type FormFieldComponent = FC<FormFieldComponentProps>;
68
+
69
+ export type FormFieldMap = Record<string, FormFieldComponent>;
70
+
71
+ export type FormFieldProvider = (props: {
72
+ prop: string;
73
+ schema: Schema.Schema<any>;
74
+ fieldProps: FormFieldComponentProps;
75
+ }) => ReactElement | null | undefined;
76
+
77
+ //
78
+ // FormFieldLabel
79
+ //
80
+
81
+ export type FormFieldLabelProps = ThemedClassName<
82
+ {
83
+ asChild?: boolean;
84
+ error?: string;
85
+ /**
86
+ * JSON path of the field this label describes (e.g. `runtime.client.storage.persistent`).
87
+ * Surfaced as a hover tooltip on the label when the enclosing `Form.Root`
88
+ * has `tooltips` enabled (the default) -- useful for spotting which field
89
+ * maps to which path when authoring schemas or filing bugs against a form.
90
+ * Callers can supply the path unconditionally; the label suppresses the
91
+ * tooltip when `Form.Root tooltips={false}`.
92
+ */
93
+ path?: string;
94
+ /**
95
+ * Trailing button rendered at the end of the label row (third grid column).
96
+ * Used by nested-object field sets to surface a collapse toggle.
97
+ */
98
+ button?: ReactNode;
99
+ onClick?: () => void;
100
+ } & Pick<FormFieldComponentProps, 'label' | 'readonly'>
101
+ >;
102
+
103
+ export const FormFieldLabel = ({
104
+ classNames,
105
+ label,
106
+ error,
107
+ readonly,
108
+ asChild,
109
+ path,
110
+ button,
111
+ onClick,
112
+ }: FormFieldLabelProps) => {
113
+ const tooltips = useFormTooltips();
114
+ const Label = readonly || asChild ? 'span' : Input.Label;
115
+ const labelNode = <Label className={mx(inputTextLabel, 'text-sm')}>{label}</Label>;
116
+
117
+ return (
118
+ <div
119
+ className={mx('grid grid-cols-[1fr_auto_auto] items-center select-none', onClick && 'cursor-pointer', classNames)}
120
+ onClick={onClick}
121
+ >
122
+ {tooltips && path ? (
123
+ <Tooltip.Trigger asChild content={path} side='bottom'>
124
+ {labelNode}
125
+ </Tooltip.Trigger>
126
+ ) : (
127
+ labelNode
128
+ )}
129
+ {error ? (
130
+ <Tooltip.Trigger asChild content={error} side='bottom'>
131
+ <Icon icon='ph--warning--regular' size={4} classNames='text-error-text' />
132
+ </Tooltip.Trigger>
133
+ ) : (
134
+ <span />
135
+ )}
136
+ {button}
137
+ </div>
138
+ );
139
+ };
140
+
141
+ FormFieldLabel.displayName = 'Form.FieldLabel';
142
+
143
+ //
144
+ // FormFieldWrapper
145
+ //
146
+
147
+ export type FormFieldWrapperProps<T = any> = Pick<
148
+ FormFieldComponentProps,
149
+ 'readonly' | 'label' | 'layout' | 'getStatus' | 'getValue' | 'jsonPath' | 'format'
150
+ > & {
151
+ children?: (props: { value: T }) => ReactNode;
152
+ };
153
+
154
+ /**
155
+ * Formats a value for `static` (read-only, plain-DOM) presentation based on its
156
+ * type `format`. Dates/times are rendered human-readable; everything else falls
157
+ * back to `String(value)`.
158
+ */
159
+ const formatStaticValue = (value: unknown, format?: Format.TypeFormat): string => {
160
+ if (value == null) {
161
+ return '';
162
+ }
163
+
164
+ switch (format) {
165
+ case Format.TypeFormat.DateTime:
166
+ case Format.TypeFormat.Date:
167
+ case Format.TypeFormat.Time: {
168
+ const date = new Date(value as string);
169
+ if (Number.isNaN(date.getTime())) {
170
+ return String(value);
171
+ }
172
+ const pattern = format === Format.TypeFormat.DateTime ? 'PPp' : format === Format.TypeFormat.Date ? 'PP' : 'p';
173
+ return formatDate(date, pattern);
174
+ }
175
+ default:
176
+ return String(value);
177
+ }
178
+ };
179
+
180
+ export const FormFieldWrapper = <T,>(props: FormFieldWrapperProps<T>) => {
181
+ const { children, readonly, layout, label, jsonPath, format, getStatus, getValue } = props;
182
+ const { status, error } = getStatus();
183
+
184
+ const value = getValue();
185
+ if (layout === 'static' && value == null) {
186
+ return null;
187
+ }
188
+
189
+ const str = formatStaticValue(value, format);
190
+
191
+ return (
192
+ <div className='contents'>
193
+ <Input.Root validationValence={status}>
194
+ {layout !== 'inline' && <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />}
195
+ {layout === 'static' ? (
196
+ <p className='truncate min-w-0' title={str}>
197
+ {str}
198
+ </p>
199
+ ) : children ? (
200
+ children({ value })
201
+ ) : null}
202
+ {layout === 'full' && error && (
203
+ <Input.DescriptionAndValidation>
204
+ <Input.Validation>{error}</Input.Validation>
205
+ </Input.DescriptionAndValidation>
206
+ )}
207
+ </Input.Root>
208
+ </div>
209
+ );
210
+ };
211
+
212
+ //
213
+ // FormFieldErrorBoundary
214
+ //
215
+
216
+ type FormFieldErrorState = {
217
+ error: Error | undefined;
218
+ };
219
+
220
+ type FormFieldErrorBoundaryProps = PropsWithChildren<{
221
+ path?: (string | number)[];
222
+ }>;
223
+
224
+ export class FormFieldErrorBoundary extends Component<FormFieldErrorBoundaryProps, FormFieldErrorState> {
225
+ static getDerivedStateFromError(error: Error): { error: Error } {
226
+ return { error };
227
+ }
228
+
229
+ override state = { error: undefined };
230
+
231
+ override componentDidUpdate(prevProps: FormFieldErrorBoundaryProps) {
232
+ if (prevProps.path !== this.props.path) {
233
+ this.resetError();
234
+ }
235
+ }
236
+
237
+ override render() {
238
+ if (this.state.error) {
239
+ return (
240
+ <div className='flex gap-2 border border-rose-bg font-mono text-sm'>
241
+ <span className='bg-rose-bg text-base-fg px-1 font-thin'>ERROR</span>
242
+ {String(this.props.path?.join('.'))}
243
+ </div>
244
+ );
245
+ }
246
+
247
+ return this.props.children;
248
+ }
249
+
250
+ private resetError() {
251
+ this.setState({ error: undefined });
252
+ }
253
+ }