@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,206 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Schema from 'effect/Schema';
7
+ import React, { useMemo } from 'react';
8
+ import { expect, userEvent } from 'storybook/test';
9
+
10
+ import { Filter, Format, Obj, Ref } from '@dxos/echo';
11
+ import { useQuery } from '@dxos/react-client/echo';
12
+ import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
13
+ import { Panel } from '@dxos/react-ui';
14
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
15
+ import { Text } from '@dxos/schema';
16
+
17
+ import { translations } from '#translations';
18
+
19
+ import { TestLayout } from '../../testing';
20
+ import { Form } from '../Form';
21
+
22
+ //
23
+ // String-backed markdown.
24
+ //
25
+
26
+ const StringSchema = Schema.Struct({
27
+ notes: Schema.String.pipe(Format.FormatAnnotation.set(Format.TypeFormat.Markdown)).annotations({ title: 'Notes' }),
28
+ });
29
+
30
+ const StringStory = () => (
31
+ <TestLayout>
32
+ <Form.Root schema={StringSchema} defaultValues={{ notes: '# Hello\n\nMarkdown text *here*.' }}>
33
+ <Form.Viewport>
34
+ <Form.Content>
35
+ <Form.FieldSet />
36
+ </Form.Content>
37
+ </Form.Viewport>
38
+ </Form.Root>
39
+ </TestLayout>
40
+ );
41
+
42
+ //
43
+ // Ref<Text>-backed markdown.
44
+ //
45
+
46
+ const TextNoteHolder = Schema.Struct({
47
+ instructions: Ref.Ref(Text.Text)
48
+ .pipe(Format.FormatAnnotation.set(Format.TypeFormat.Markdown))
49
+ .annotations({ title: 'Instructions' }),
50
+ });
51
+
52
+ const RefStory = () => {
53
+ const { space } = useClientStory();
54
+ const [text] = useQuery(space?.db, Filter.type(Text.Text));
55
+ const values = useMemo(() => (text ? { instructions: Ref.make(text) } : undefined), [text]);
56
+
57
+ if (!space || !values) {
58
+ return null;
59
+ }
60
+
61
+ return (
62
+ <TestLayout>
63
+ <Panel.Root>
64
+ <Panel.Content asChild>
65
+ <Form.Root schema={TextNoteHolder} values={values as any} db={space.db}>
66
+ <Form.Viewport>
67
+ <Form.Content>
68
+ <Form.FieldSet />
69
+ </Form.Content>
70
+ </Form.Viewport>
71
+ </Form.Root>
72
+ </Panel.Content>
73
+ </Panel.Root>
74
+ </TestLayout>
75
+ );
76
+ };
77
+
78
+ //
79
+ // Ref<Text> empty — shows the create button.
80
+ //
81
+
82
+ const EmptyRefSchema = Schema.Struct({
83
+ instructions: Schema.optional(
84
+ Ref.Ref(Text.Text)
85
+ .pipe(Format.FormatAnnotation.set(Format.TypeFormat.Markdown))
86
+ .annotations({ title: 'Instructions' }),
87
+ ),
88
+ });
89
+
90
+ const EmptyRefStory = () => {
91
+ const { space } = useClientStory();
92
+ if (!space) {
93
+ return null;
94
+ }
95
+
96
+ return (
97
+ <TestLayout>
98
+ <Panel.Root>
99
+ <Panel.Content asChild>
100
+ <Form.Root schema={EmptyRefSchema} defaultValues={{}} db={space.db}>
101
+ <Form.Viewport>
102
+ <Form.Content>
103
+ <Form.FieldSet />
104
+ </Form.Content>
105
+ </Form.Viewport>
106
+ </Form.Root>
107
+ </Panel.Content>
108
+ </Panel.Root>
109
+ </TestLayout>
110
+ );
111
+ };
112
+
113
+ const meta = {
114
+ title: 'ui/react-ui-form/MarkdownField',
115
+ decorators: [withTheme(), withLayout({ layout: 'column' })],
116
+ parameters: {
117
+ layout: 'fullscreen',
118
+ translations,
119
+ },
120
+ } satisfies Meta;
121
+
122
+ export default meta;
123
+
124
+ type Story = StoryObj<typeof meta>;
125
+
126
+ export const StringBacked: Story = {
127
+ render: () => <StringStory />,
128
+ };
129
+
130
+ // Regression test: keystrokes into a string-backed markdown field must not
131
+ // blur the editor. Previously the EditorView was destroyed and recreated on
132
+ // every change because `onChange` was a useTextEditor dep and form callbacks
133
+ // are unstable across renders.
134
+ export const StringBackedKeepsFocus: Story = {
135
+ render: () => (
136
+ <TestLayout>
137
+ <Form.Root schema={StringSchema} defaultValues={{ notes: '' }}>
138
+ <Form.Viewport>
139
+ <Form.Content>
140
+ <Form.FieldSet />
141
+ </Form.Content>
142
+ </Form.Viewport>
143
+ </Form.Root>
144
+ </TestLayout>
145
+ ),
146
+ play: async ({ canvasElement }) => {
147
+ const waitFor = async <T,>(predicate: () => T | null | undefined, message: string): Promise<T> => {
148
+ for (let attempt = 0; attempt < 50; attempt++) {
149
+ const value = predicate();
150
+ if (value) {
151
+ return value;
152
+ }
153
+ await new Promise((resolve) => setTimeout(resolve, 100));
154
+ }
155
+ throw new Error(message);
156
+ };
157
+
158
+ const editorRoot = await waitFor(
159
+ () => canvasElement.querySelector<HTMLElement>('.cm-editor'),
160
+ 'CodeMirror editor root (.cm-editor) not found',
161
+ );
162
+ const editorContent = editorRoot.querySelector<HTMLElement>('.cm-content')!;
163
+ await expect(editorContent).toBeVisible();
164
+
165
+ // Focus editor and wait for focus to settle inside the editor root.
166
+ editorContent.focus();
167
+ await waitFor(() => (editorRoot.contains(document.activeElement) ? true : null), 'Editor did not receive focus');
168
+
169
+ // Type several characters; focus must be preserved inside the editor root
170
+ // after every keystroke. Regression: previously the EditorView was
171
+ // destroyed and recreated on every change, which detached the focused
172
+ // contentDOM and blurred the input.
173
+ const phrase = 'hello world';
174
+ for (const ch of phrase) {
175
+ await userEvent.keyboard(ch);
176
+ await expect(editorRoot.contains(document.activeElement)).toBe(true);
177
+ }
178
+
179
+ await expect(editorContent).toHaveTextContent(phrase);
180
+ },
181
+ };
182
+
183
+ export const RefPopulated: Story = {
184
+ render: () => <RefStory />,
185
+ decorators: [
186
+ withClientProvider({
187
+ createIdentity: true,
188
+ createSpace: true,
189
+ types: [Text.Text],
190
+ onCreateSpace: async ({ space }) => {
191
+ space.db.add(Obj.make(Text.Text, { content: '# Magazine brief\n\nLong-form text describing what to gather.' }));
192
+ },
193
+ }),
194
+ ],
195
+ };
196
+
197
+ export const RefEmpty: Story = {
198
+ render: () => <EmptyRefStory />,
199
+ decorators: [
200
+ withClientProvider({
201
+ createIdentity: true,
202
+ createSpace: true,
203
+ types: [Text.Text],
204
+ }),
205
+ ],
206
+ };
@@ -0,0 +1,167 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { useAtomValue } from '@effect-atom/atom-react';
6
+ import React, { useCallback, useMemo } from 'react';
7
+
8
+ import { type Database, Obj, Ref } from '@dxos/echo';
9
+ import { createDocAccessor } from '@dxos/echo-client';
10
+ import { Button, Icon, Input, useTranslation } from '@dxos/react-ui';
11
+ import { Editor, useBasicMarkdownExtensions } from '@dxos/react-ui-editor';
12
+ import { Text } from '@dxos/schema';
13
+ import { createDataExtensions } from '@dxos/ui-editor';
14
+
15
+ import { translationKey } from '#translations';
16
+
17
+ import { type FormFieldComponentProps, FormFieldLabel } from '../FormFieldComponent';
18
+
19
+ const editorClassNames =
20
+ 'transition-colors bg-input-surface focus-within:bg-focus-surface border border-separator rounded-xs p-1 px-2';
21
+
22
+ /**
23
+ * Form field that edits a markdown value in a CodeMirror editor.
24
+ * Supports two backings:
25
+ * - `Schema.String` annotated with `Format.TypeFormat.Markdown`: edited as plain text via `getValue`/`onValueChange`.
26
+ * - `Ref<Text>` annotated with `Format.TypeFormat.Markdown`: edited in-place via an Automerge doc accessor.
27
+ * When the ref is empty and a database is available, a create button is shown to allocate a new Text.
28
+ */
29
+ export const MarkdownField = ({
30
+ type,
31
+ readonly,
32
+ label,
33
+ jsonPath,
34
+ placeholder,
35
+ layout,
36
+ db,
37
+ getStatus,
38
+ getValue,
39
+ onValueChange,
40
+ }: FormFieldComponentProps) => {
41
+ const { status, error } = getStatus();
42
+ const isRef = Ref.isRefType(type);
43
+ const value = getValue();
44
+
45
+ if ((readonly || layout === 'static') && value == null) {
46
+ return null;
47
+ }
48
+
49
+ const renderEditor = () => {
50
+ if (isRef) {
51
+ const reference = value as Ref.Ref<any> | undefined;
52
+ if (reference) {
53
+ return <RefMarkdownEditor reference={reference} placeholder={placeholder} />;
54
+ }
55
+
56
+ if (readonly) {
57
+ return null;
58
+ }
59
+
60
+ return <CreateTextButton db={db} disabled={!db} onCreate={(ref) => onValueChange(type, ref)} />;
61
+ }
62
+
63
+ return (
64
+ <StringMarkdownEditor
65
+ value={(value as string | undefined) ?? ''}
66
+ placeholder={placeholder}
67
+ readonly={!!readonly}
68
+ onChange={(next) => onValueChange(type, next)}
69
+ />
70
+ );
71
+ };
72
+
73
+ const renderStatic = () => {
74
+ if (isRef) {
75
+ const reference = value as Ref.Ref<any> | undefined;
76
+ return reference ? <RefStaticText reference={reference} /> : null;
77
+ }
78
+ return <p className='whitespace-pre-wrap'>{(value as string | undefined) ?? ''}</p>;
79
+ };
80
+
81
+ return (
82
+ <Input.Root validationValence={status}>
83
+ {layout !== 'inline' && <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />}
84
+ {layout === 'static' ? renderStatic() : renderEditor()}
85
+ {layout === 'full' && <Input.Validation>{error}</Input.Validation>}
86
+ </Input.Root>
87
+ );
88
+ };
89
+
90
+ /** Read-only static rendering for a `Ref<Text>` value: resolve the ref and print its content. */
91
+ const RefStaticText = ({ reference }: { reference: Ref.Ref<any> }) => {
92
+ const text = useAtomValue(useMemo(() => reference.atom, [reference]));
93
+ if (!text?.content) {
94
+ return null;
95
+ }
96
+ return <p className='whitespace-pre-wrap'>{text.content}</p>;
97
+ };
98
+
99
+ type RefMarkdownEditorProps = {
100
+ reference: Ref.Ref<any>;
101
+ placeholder?: string;
102
+ };
103
+
104
+ const RefMarkdownEditor = ({ reference, placeholder }: RefMarkdownEditorProps) => {
105
+ const text = useAtomValue(useMemo(() => reference.atom, [reference]));
106
+ const dataExtensions = useMemo(
107
+ () => (text ? [createDataExtensions({ id: reference.uri, text: createDocAccessor(text, ['content']) })] : []),
108
+ [text, reference],
109
+ );
110
+ const extensions = useBasicMarkdownExtensions({ placeholder, extensions: dataExtensions });
111
+ if (!text) {
112
+ return null;
113
+ }
114
+
115
+ return (
116
+ <Editor.Root>
117
+ <Editor.View classNames={editorClassNames} extensions={extensions} />
118
+ </Editor.Root>
119
+ );
120
+ };
121
+
122
+ type StringMarkdownEditorProps = {
123
+ value: string;
124
+ placeholder?: string;
125
+ readonly?: boolean;
126
+ onChange: (value: string) => void;
127
+ };
128
+
129
+ const StringMarkdownEditor = ({ value, placeholder, readonly, onChange }: StringMarkdownEditorProps) => {
130
+ const extensions = useBasicMarkdownExtensions({ placeholder });
131
+ const handleChange = useCallback((next: string) => onChange(next), [onChange]);
132
+
133
+ return (
134
+ <Editor.Root>
135
+ <Editor.View
136
+ classNames={editorClassNames}
137
+ extensions={extensions}
138
+ value={value}
139
+ onChange={readonly ? undefined : handleChange}
140
+ />
141
+ </Editor.Root>
142
+ );
143
+ };
144
+
145
+ type CreateTextButtonProps = {
146
+ db?: Database.Database;
147
+ disabled?: boolean;
148
+ onCreate: (ref: Ref.Ref<Text.Text>) => void;
149
+ };
150
+
151
+ const CreateTextButton = ({ db, disabled, onCreate }: CreateTextButtonProps) => {
152
+ const { t } = useTranslation(translationKey);
153
+ const handleClick = useCallback(() => {
154
+ if (!db) {
155
+ return;
156
+ }
157
+ const text = db.add(Obj.make(Text.Text, { content: '' }));
158
+ onCreate(Ref.make(text));
159
+ }, [db, onCreate]);
160
+
161
+ return (
162
+ <Button onClick={handleClick} disabled={disabled}>
163
+ <Icon icon='ph--plus--regular' size={4} />
164
+ <span>{t('create-text.label')}</span>
165
+ </Button>
166
+ );
167
+ };
@@ -0,0 +1,76 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useEffect, useState } from 'react';
6
+
7
+ import { Input, type TextInputProps } from '@dxos/react-ui';
8
+ import { safeParseFloat } from '@dxos/util';
9
+
10
+ import { type FormFieldComponentProps, FormFieldWrapper } from '../FormFieldComponent';
11
+
12
+ export const NumberField = ({
13
+ type,
14
+ readonly,
15
+ placeholder,
16
+ getValue,
17
+ onValueChange,
18
+ onBlur,
19
+ ...props
20
+ }: FormFieldComponentProps<number>) => {
21
+ // Track raw string input so the user can clear the field before typing a new number.
22
+ // We only commit to onValueChange when the raw string parses to a valid number.
23
+ const [raw, setRaw] = useState<string>(() => {
24
+ const v = getValue();
25
+ return v !== undefined ? String(v) : '';
26
+ });
27
+
28
+ // Sync display when an external change updates the committed value (e.g. reactive form
29
+ // calculations). Only overwrite raw when the external value differs from what raw parses
30
+ // to, preserving partial edits like "1." which correctly parse to 1.
31
+ const externalValue = getValue();
32
+ useEffect(() => {
33
+ if (externalValue !== safeParseFloat(raw)) {
34
+ setRaw(externalValue !== undefined ? String(externalValue) : '');
35
+ }
36
+ }, [externalValue]); // eslint-disable-line react-hooks/exhaustive-deps
37
+
38
+ const handleChange = useCallback<NonNullable<TextInputProps['onChange']>>(
39
+ (event) => {
40
+ const value = event.target.value;
41
+ setRaw(value);
42
+ const parsed = safeParseFloat(value);
43
+ if (parsed !== undefined) {
44
+ onValueChange(type, parsed);
45
+ }
46
+ },
47
+ [type, onValueChange],
48
+ );
49
+
50
+ const handleBlur = useCallback(
51
+ (event: React.FocusEvent<HTMLElement>) => {
52
+ // If the field was left empty or invalid, reset to the last committed value.
53
+ if (safeParseFloat(raw) === undefined) {
54
+ const committed = getValue();
55
+ setRaw(committed !== undefined ? String(committed) : '');
56
+ }
57
+ onBlur(event);
58
+ },
59
+ [raw, getValue, onBlur],
60
+ );
61
+
62
+ return (
63
+ <FormFieldWrapper<number> readonly={readonly} getValue={getValue} {...props}>
64
+ {() => (
65
+ <Input.TextInput
66
+ type='number'
67
+ disabled={!!readonly}
68
+ placeholder={placeholder}
69
+ value={raw}
70
+ onChange={handleChange}
71
+ onBlur={handleBlur}
72
+ />
73
+ )}
74
+ </FormFieldWrapper>
75
+ );
76
+ };
@@ -0,0 +1,45 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { type RefOption } from '../../ObjectPicker';
8
+ import { findRefOption } from './RefField';
9
+
10
+ // Sample qualified self URIs as produced by an in-space object (Entity.getURI / `echo://<space>/<id>`).
11
+ const SPACE_ID = 'BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE';
12
+ const ENTITY_ID = '01J00J9B45YHYSGZQTQMSKMGJ6';
13
+ const QUALIFIED = `echo://${SPACE_ID}/${ENTITY_ID}`;
14
+ const LOCAL = `echo:/${ENTITY_ID}`;
15
+
16
+ const options: RefOption[] = [
17
+ { id: QUALIFIED, label: 'Target' },
18
+ { id: 'echo://BA25QRC2FEWCSAMRP4RZL65LWJ7352CKE/01J00OTHER0000000000000000', label: 'Other' },
19
+ ];
20
+
21
+ describe('findRefOption', () => {
22
+ test('matches an exact qualified ref', ({ expect }) => {
23
+ expect(findRefOption({ '/': QUALIFIED }, options)?.label).toBe('Target');
24
+ });
25
+
26
+ test('matches a bare local ref against a qualified option by entity id', ({ expect }) => {
27
+ // `Ref.make` yields the local form; the option is keyed by the qualified self URI.
28
+ expect(findRefOption({ '/': LOCAL }, options)?.label).toBe('Target');
29
+ });
30
+
31
+ test('returns undefined for a non-ref value', ({ expect }) => {
32
+ expect(findRefOption('not-a-ref', options)).toBeUndefined();
33
+ expect(findRefOption(undefined, options)).toBeUndefined();
34
+ });
35
+
36
+ test('returns undefined when no option matches', ({ expect }) => {
37
+ expect(findRefOption({ '/': 'echo:/01J00MISSING0000000000000000' }, options)).toBeUndefined();
38
+ });
39
+
40
+ test('does not match a qualified ref against a same-entity-id option from a different space', ({ expect }) => {
41
+ // The entity id coincides but the space authority differs; ids are only unique within a space.
42
+ const otherSpace = `echo://BZ25QRC2FEWCSAMRP4RZL65LWJ7352CKE/${ENTITY_ID}`;
43
+ expect(findRefOption({ '/': otherSpace }, options)).toBeUndefined();
44
+ });
45
+ });