@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,55 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Input } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/ui-theme';
9
+ import { safeParseFloat } from '@dxos/util';
10
+
11
+ import { type FormFieldComponentProps, FormFieldLabel } from '../FormFieldComponent';
12
+
13
+ const gridCols = ['grid-cols-1', 'grid-cols-2', 'grid-cols-3', 'grid-cols-4'];
14
+
15
+ export const TupleField = ({
16
+ binding,
17
+ type,
18
+ readonly,
19
+ label,
20
+ jsonPath,
21
+ getStatus,
22
+ getValue,
23
+ onValueChange,
24
+ onBlur,
25
+ }: FormFieldComponentProps<Record<string, number>> & {
26
+ binding: string[];
27
+ }) => {
28
+ const { status, error } = getStatus();
29
+
30
+ // TODO(burdon): Generalize number/float/string, etc.
31
+ const values: Record<string, number> = getValue() ?? {};
32
+
33
+ return (
34
+ <Input.Root validationValence={status}>
35
+ <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />
36
+ <div className={mx('grid gap-form-gap', gridCols[binding.length - 1])}>
37
+ {binding.map((prop) => (
38
+ <Input.TextInput
39
+ key={prop}
40
+ type='number'
41
+ disabled={!!readonly}
42
+ value={values[prop]}
43
+ onChange={(event) => {
44
+ onValueChange(type, {
45
+ ...values,
46
+ [prop]: safeParseFloat(event.target.value, 0),
47
+ });
48
+ }}
49
+ onBlur={onBlur}
50
+ />
51
+ ))}
52
+ </div>
53
+ </Input.Root>
54
+ );
55
+ };
@@ -0,0 +1,17 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './ArrayField';
6
+ export * from './BooleanField';
7
+ export * from './DateField';
8
+ export * from './GeoPointField';
9
+ export * from './InlineRefField';
10
+ export * from './MarkdownField';
11
+ export * from './NumberField';
12
+ export * from './RefField';
13
+ export * from './SelectField';
14
+ export * from './SelectOptionField';
15
+ export * from './TextField';
16
+ export * from './TextAreaField';
17
+ export * from './TupleField';
@@ -2,8 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export * from './custom';
6
- export * from './Defaults';
5
+ export * from './fields';
6
+
7
7
  export * from './Form';
8
- export * from './FormContext';
9
- export * from './Input';
8
+ export * from './FormFieldComponent';
9
+ export * from './FormTooltipsContext';
10
+ export * from './meta-tags';
11
+ export * from './Layout';
@@ -0,0 +1,47 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+ import * as SchemaAST from 'effect/SchemaAST';
7
+ import { describe, test } from 'vitest';
8
+
9
+ import { Obj, Ref, Tag } from '@dxos/echo';
10
+
11
+ import { META_TAGS_KEY, withMetaTags } from './meta-tags';
12
+
13
+ // A feed-host schema whose own `tags` field is a `TagIndex` record (tagId -> objectId[]), not an
14
+ // array — mirrors plugin-commerce `Search`, plugin-inbox `Mailbox`, plugin-feed `Subscription`.
15
+ const TagIndexHost = Schema.Struct({
16
+ name: Schema.String.pipe(Schema.optional),
17
+ tags: Schema.Record({ key: Schema.String, value: Schema.Array(Obj.ID) }).pipe(Schema.optional),
18
+ });
19
+
20
+ const propertyNames = (schema: Schema.Schema.AnyNoContext): string[] =>
21
+ SchemaAST.getPropertySignatures(schema.ast).map((property) => property.name.toString());
22
+
23
+ describe('withMetaTags', () => {
24
+ test('keying meta-tags as `tags` collides with a schema-declared `tags` record (regression)', ({ expect }) => {
25
+ // The pre-fix shape: splice a `tags: Array<Ref<Tag>>` onto a schema that already declares `tags`.
26
+ // `Schema.extend` cannot merge an array with a record at the same key, hence the companion crash:
27
+ // "overlapping types at path: [\"tags\"]".
28
+ expect(() =>
29
+ Schema.Struct({ tags: Schema.Array(Ref.Ref(Tag.Tag)).pipe(Schema.optional) }).pipe(Schema.extend(TagIndexHost)),
30
+ ).toThrow(/tags/i);
31
+ });
32
+
33
+ test('splices meta-tags under `_tags` without colliding with a schema-declared `tags`', ({ expect }) => {
34
+ const schema = withMetaTags(TagIndexHost);
35
+ const names = propertyNames(schema);
36
+ expect(names).toContain(META_TAGS_KEY);
37
+ expect(names).toContain('tags');
38
+ expect(names).not.toContain('id');
39
+ });
40
+
41
+ test('still splices meta-tags onto a schema with no `tags` field', ({ expect }) => {
42
+ const Plain = Schema.Struct({ name: Schema.String });
43
+ const names = propertyNames(withMetaTags(Plain));
44
+ expect(names).toContain(META_TAGS_KEY);
45
+ expect(names).toContain('name');
46
+ });
47
+ });
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+
7
+ import { Ref, Tag } from '@dxos/echo';
8
+
9
+ import { omitId } from './Form';
10
+
11
+ /**
12
+ * Form-field key for the synthetic meta-tags array spliced into property/create forms.
13
+ *
14
+ * An object's tags live in `Obj.getMeta(obj).tags` (off-schema), so the form surfaces them as an
15
+ * extra field rather than reading the schema. The key is underscore-prefixed so it never collides
16
+ * with a `tags` field an object schema declares itself — e.g. a `TagIndex` record on a feed host,
17
+ * whose `tags` is `Record<tagId, objectId[]>`, not an array. Extending such a schema with a `tags`
18
+ * array threw "overlapping types at path: [\"tags\"]"; the disjoint `_tags` key avoids it. The
19
+ * human-facing label is restored via the `title` annotation on {@link withMetaTags}.
20
+ */
21
+ export const META_TAGS_KEY = '_tags';
22
+
23
+ /**
24
+ * Splices the synthetic meta-tags array (an object's `meta.tags`, surfaced as {@link Tag} refs) onto
25
+ * a schema for editing and drops `id`. Keyed by {@link META_TAGS_KEY} so it never collides with a
26
+ * `tags` field the schema declares itself.
27
+ */
28
+ export const withMetaTags = (schema: Schema.Schema.AnyNoContext) =>
29
+ omitId(
30
+ Schema.Struct({
31
+ [META_TAGS_KEY]: Schema.Array(Ref.Ref(Tag.Tag)).pipe(Schema.annotations({ title: 'Tags' }), Schema.optional),
32
+ }).pipe(Schema.extend(schema)),
33
+ );
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React from 'react';
7
+
8
+ import { Filter, Obj, Ref, Tag } from '@dxos/echo';
9
+ import { useQuery } from '@dxos/react-client/echo';
10
+ import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
11
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
12
+ import { Person } from '@dxos/types';
13
+
14
+ import { translations } from '#translations';
15
+
16
+ import { ObjectForm } from './ObjectForm';
17
+
18
+ const DefaultStory = () => {
19
+ const { space } = useClientStory();
20
+ const [person] = useQuery(space?.db, Filter.type(Person.Person));
21
+ if (!person) {
22
+ return <></>;
23
+ }
24
+
25
+ return <ObjectForm object={person} type={Person.Person} />;
26
+ };
27
+
28
+ const meta = {
29
+ title: 'ui/react-ui-form/ObjectForm',
30
+ render: DefaultStory,
31
+ decorators: [
32
+ withTheme(),
33
+ withLayout({ layout: 'column', classNames: 'p-2', scroll: true }),
34
+ withClientProvider({
35
+ types: [Person.Person, Tag.Tag],
36
+ createIdentity: true,
37
+ createSpace: true,
38
+ onCreateSpace: async ({ space }) => {
39
+ const tag = space.db.add(Tag.make({ label: 'Friend', hue: 'emerald' }));
40
+ const person = space.db.add(
41
+ Obj.make(Person.Person, {
42
+ fullName: 'Alice Carroll',
43
+ jobTitle: 'Engineer',
44
+ emails: [{ value: 'alice@example.com' }],
45
+ }),
46
+ );
47
+ Obj.update(person, (person) => {
48
+ Obj.getMeta(person).tags = [Ref.make(tag)];
49
+ });
50
+ },
51
+ }),
52
+ ],
53
+ parameters: {
54
+ translations,
55
+ },
56
+ } satisfies Meta<typeof DefaultStory>;
57
+
58
+ export default meta;
59
+
60
+ type Story = StoryObj<typeof meta>;
61
+
62
+ export const Default: Story = {};
@@ -0,0 +1,111 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useMemo } from 'react';
6
+
7
+ import { Obj, Ref, Tag, Type } from '@dxos/echo';
8
+ import { SchemaEx } from '@dxos/effect';
9
+ import { invariant } from '@dxos/invariant';
10
+ import { HuePicker } from '@dxos/react-ui-pickers';
11
+
12
+ import { translationKey } from '#translations';
13
+
14
+ import { Form, type FormFieldMap, META_TAGS_KEY, withMetaTags } from '../Form';
15
+
16
+ export type ObjectFormProps = {
17
+ type: Type.AnyEntity;
18
+ object: Obj.Unknown;
19
+ };
20
+
21
+ const createFieldMap: FormFieldMap = {
22
+ hue: ({ type, label, layout, getValue, onValueChange }) => {
23
+ const handleChange = useCallback((nextHue: string) => onValueChange(type, nextHue), [onValueChange, type]);
24
+ const handleReset = useCallback(() => onValueChange(type, undefined), [onValueChange, type]);
25
+ return (
26
+ <>
27
+ {layout !== 'inline' && <Form.Label label={label} />}
28
+ <HuePicker value={getValue()} onChange={handleChange} onReset={handleReset} />
29
+ </>
30
+ );
31
+ },
32
+ };
33
+
34
+ export const ObjectForm = ({ object, type }: ObjectFormProps) => {
35
+ const db = Obj.getDatabase(object);
36
+ const meta = Obj.getMeta(object);
37
+ // `meta.tags` already holds `Ref<Tag>`s (materialized by the database handler).
38
+ const tags = [...meta.tags];
39
+ const values = useMemo(() => ({ [META_TAGS_KEY]: tags, ...object }), [object, tags]);
40
+ const formSchema = useMemo(() => withMetaTags(Type.getSchema(type)), [type]);
41
+
42
+ const handleCreate = useCallback((type: Type.AnyEntity, values: any) => {
43
+ invariant(db);
44
+ invariant(Type.isObject(type));
45
+ const newObject = db.add(Obj.make(type, values));
46
+ if (Obj.instanceOf(Tag.Tag, newObject)) {
47
+ Obj.update(object, (object) => {
48
+ Obj.getMeta(object).tags = [...Obj.getMeta(object).tags, Ref.make(newObject)];
49
+ });
50
+ }
51
+ }, []);
52
+
53
+ // TODO(wittjosiah): Use FormRootProps type.
54
+ const handleChange = useCallback(
55
+ (
56
+ { [META_TAGS_KEY]: metaTags, ...values }: any,
57
+ { isValid, changed }: { isValid: boolean; changed: Record<SchemaEx.JsonPath, boolean> },
58
+ ) => {
59
+ if (!isValid) {
60
+ return;
61
+ }
62
+
63
+ const changedPaths = Object.keys(changed).filter(
64
+ (path) => changed[path as SchemaEx.JsonPath],
65
+ ) as SchemaEx.JsonPath[];
66
+
67
+ // Handle meta-tags separately using Obj.update.
68
+ const hasTagsChange = changedPaths.some((path) => SchemaEx.splitJsonPath(path)[0] === META_TAGS_KEY);
69
+ if (hasTagsChange) {
70
+ Obj.update(object, (object) => {
71
+ // Copy so later in-place form mutations don't bypass the `Obj.update` boundary.
72
+ Obj.getMeta(object).tags = Array.isArray(metaTags) ? [...(metaTags as Ref.Ref<Tag.Tag>[])] : [];
73
+ });
74
+ }
75
+
76
+ // Handle other property changes.
77
+ const nonTagPaths = changedPaths.filter((path) => SchemaEx.splitJsonPath(path)[0] !== META_TAGS_KEY);
78
+ if (nonTagPaths.length > 0) {
79
+ Obj.update(object, () => {
80
+ for (const path of nonTagPaths) {
81
+ const parts = SchemaEx.splitJsonPath(path);
82
+ const value = Obj.getValue(values, parts);
83
+ Obj.setValue(object, parts, value);
84
+ }
85
+ });
86
+ }
87
+ },
88
+ [object],
89
+ );
90
+
91
+ return (
92
+ <Form.Root
93
+ schema={formSchema}
94
+ defaultValues={values}
95
+ createTypename={Type.getTypename(Tag.Tag)}
96
+ createOptionIcon='ph--plus--regular'
97
+ createOptionLabel={['add-tag.label', { ns: translationKey }]}
98
+ createInitialValuePath='label'
99
+ createFieldMap={createFieldMap}
100
+ db={db}
101
+ onValuesChanged={handleChange}
102
+ onCreate={handleCreate}
103
+ >
104
+ <Form.Viewport>
105
+ <Form.Content>
106
+ <Form.FieldSet />
107
+ </Form.Content>
108
+ </Form.Viewport>
109
+ </Form.Root>
110
+ );
111
+ };
@@ -2,4 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './ControlSection';
5
+ export * from './ObjectForm';
@@ -0,0 +1,212 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Schema from 'effect/Schema';
7
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
8
+ import { expect, fn, userEvent, within } from 'storybook/test';
9
+
10
+ import { Filter, Obj, Type } from '@dxos/echo';
11
+ import { random } from '@dxos/random';
12
+ import { useQuery } from '@dxos/react-client/echo';
13
+ import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
14
+ import { Button } from '@dxos/react-ui';
15
+ import { withTheme } from '@dxos/react-ui/testing';
16
+ import { Person } from '@dxos/types';
17
+ import { osTranslations } from '@dxos/ui-theme';
18
+
19
+ import { translations } from '#translations';
20
+
21
+ import { ObjectPicker } from './ObjectPicker';
22
+
23
+ random.seed(1);
24
+
25
+ const createPerson = () =>
26
+ Obj.make(Person.Person, {
27
+ fullName: random.person.fullName(),
28
+ });
29
+
30
+ const omitId = Schema.omit<any, any, ['id']>('id');
31
+ const personSchema = omitId(Type.getSchema(Person.Person));
32
+
33
+ // Mock functions for testing
34
+ const mockHandleSelect = fn();
35
+ const mockHandleCreate = fn();
36
+
37
+ const DefaultStory = () => {
38
+ const { space } = useClientStory();
39
+ const [isOpen, setIsOpen] = useState(false);
40
+
41
+ // Create sample Person objects
42
+ useEffect(() => {
43
+ if (space) {
44
+ // Create some sample Person objects for testing
45
+ Array.from({ length: 10 }).forEach(() => {
46
+ space.db.add(createPerson());
47
+ });
48
+ }
49
+ }, [space]);
50
+
51
+ // Get all objects in the space (similar to BoardArticle)
52
+ const allObjects = useQuery(space?.db, Filter.everything());
53
+
54
+ // Map objects to options format expected by ObjectPicker
55
+ const options = useMemo(
56
+ () =>
57
+ allObjects.map((obj) => ({
58
+ id: obj.id,
59
+ label: obj.fullName || obj.name || obj.title || obj.id,
60
+ hue: 'neutral' as const,
61
+ })),
62
+ [allObjects],
63
+ );
64
+
65
+ const handleCreateCallback = useCallback(
66
+ (values: any) => {
67
+ console.log('[on create]', values);
68
+ if (!space) {
69
+ return;
70
+ }
71
+ const newPerson = space.db.add(Obj.make(Person.Person, values));
72
+ mockHandleCreate(values);
73
+ return newPerson;
74
+ },
75
+ [space],
76
+ );
77
+
78
+ return (
79
+ <div className='w-96'>
80
+ <ObjectPicker.Root open={isOpen} onOpenChange={setIsOpen}>
81
+ <ObjectPicker.Trigger asChild>
82
+ <Button variant='primary' data-testid='trigger' classNames='w-full'>
83
+ Select Person
84
+ </Button>
85
+ </ObjectPicker.Trigger>
86
+ <ObjectPicker.Content
87
+ classNames='dx-card-popover-width'
88
+ options={options}
89
+ createSchema={personSchema}
90
+ createOptionLabel={['create-new-person.label', { ns: osTranslations }]}
91
+ createOptionIcon='ph--user-plus--regular'
92
+ createInitialValuePath='fullName'
93
+ onCreate={handleCreateCallback}
94
+ onSelect={mockHandleSelect}
95
+ />
96
+ </ObjectPicker.Root>
97
+ </div>
98
+ );
99
+ };
100
+
101
+ const meta = {
102
+ title: 'ui/react-ui-form/ObjectPicker',
103
+ render: DefaultStory,
104
+ decorators: [
105
+ withTheme(),
106
+ withClientProvider({
107
+ types: [Person.Person],
108
+ createIdentity: true,
109
+ createSpace: true,
110
+ }),
111
+ ],
112
+ parameters: {
113
+ layout: 'centered',
114
+ controls: { disable: true },
115
+ translations,
116
+ },
117
+ } satisfies Meta<typeof DefaultStory>;
118
+
119
+ export default meta;
120
+
121
+ type Story = StoryObj<typeof meta>;
122
+
123
+ export const Default: Story = {};
124
+
125
+ export const WithTest: Story = {
126
+ play: async ({ canvasElement }) => {
127
+ const canvas = within(canvasElement);
128
+ const body = within(document.body);
129
+
130
+ // Find and click the trigger button.
131
+ const triggerButton = await canvas.findByTestId('trigger', undefined, { timeout: 5000 });
132
+ await expect(triggerButton).toBeVisible();
133
+ await userEvent.click(triggerButton);
134
+
135
+ // Check that the listbox renders when the trigger is clicked.
136
+ const listbox = await body.findByRole('listbox', undefined, { timeout: 5000 });
137
+ await expect(listbox).toBeVisible();
138
+
139
+ // Find the search input.
140
+ const searchInput = await body.findByPlaceholderText('Search…');
141
+ await expect(searchInput).toBeVisible();
142
+
143
+ // Test searching filters the results - get initial options count.
144
+ const initialOptions = await body.findAllByRole('option');
145
+ const initialCount = initialOptions.length;
146
+ await expect(initialCount).toBeGreaterThan(0);
147
+
148
+ // Type a search term that should filter results.
149
+ await userEvent.type(searchInput, 'John');
150
+
151
+ // Wait a moment for filtering.
152
+ await new Promise((resolve) => setTimeout(resolve, 100));
153
+
154
+ // Check that results are filtered (should be fewer options)
155
+ const _filteredOptions = await body.findAllByRole('option');
156
+ // Note: We expect either fewer results or the same if no John exists
157
+
158
+ // Clear search and test selecting a result
159
+ await userEvent.clear(searchInput);
160
+
161
+ // Get the first option and click it
162
+ const updatedOptions = await body.findAllByRole('option');
163
+ const firstOption = updatedOptions[0];
164
+ await expect(firstOption).toBeVisible();
165
+
166
+ const _firstOptionText = firstOption.textContent;
167
+ await userEvent.click(firstOption);
168
+
169
+ // Check that clicking a result fires onSelect with that id
170
+ // The onSelect should have been called with the selected option's id
171
+ await expect(mockHandleSelect).toHaveBeenCalled();
172
+
173
+ // Re-open the picker to test create functionality.
174
+ await userEvent.click(triggerButton);
175
+
176
+ // Wait for listbox to appear again.
177
+ const newListbox = await body.findByRole('listbox', undefined, { timeout: 5000 });
178
+ await expect(newListbox).toBeVisible();
179
+
180
+ const newSearchInput = await body.findByPlaceholderText('Search…');
181
+
182
+ // Test searching an unrelated term provides the __create__ option.
183
+ const unrelatedTerm = 'ZxyUnrelatedName123';
184
+ await userEvent.type(newSearchInput, unrelatedTerm);
185
+
186
+ // Wait for the create option to appear.
187
+ await new Promise((resolve) => setTimeout(resolve, 200));
188
+
189
+ // Look for the create option.
190
+ const createOption = await body.findByRole('option', undefined, { timeout: 3000 });
191
+ await expect(createOption).toBeVisible();
192
+
193
+ // Click the create option - this should change state to the form field.
194
+ await userEvent.click(createOption);
195
+
196
+ // Check that clicking that option changes state to the form field.
197
+ const form = await body.findByTestId('create-referenced-object-form', undefined, { timeout: 5000 });
198
+ await expect(form).toBeVisible();
199
+
200
+ // Find and click the save button.
201
+ const saveButton = await within(form).findByTestId('save-button');
202
+ await expect(saveButton).toBeVisible();
203
+ await userEvent.click(saveButton);
204
+
205
+ // Check that clicking the save button calls onCreate with expected values.
206
+ await expect(mockHandleCreate).toHaveBeenCalledWith(
207
+ expect.objectContaining({
208
+ fullName: unrelatedTerm,
209
+ }),
210
+ );
211
+ },
212
+ };