@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
@@ -1,109 +1,475 @@
1
1
  //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import { type Schema } from 'effect';
6
- import React, { type ReactElement, useEffect, useMemo, useRef } from 'react';
7
-
8
- import { type BaseObject, type PropertyKey } from '@dxos/echo-schema';
9
- import { type ThemedClassName } from '@dxos/react-ui';
10
- import { cardDialogOverflow, cardSpacing } from '@dxos/react-ui-stack';
11
- import { type SchemaProperty } from '@dxos/schema';
12
-
13
- import { type FormOptions } from '../../hooks';
14
-
15
- import { FormActions, type FormOuterSpacing } from './FormActions';
16
- import { FormFields, type FormFieldsProps } from './FormContent';
17
- import { FormProvider } from './FormContext';
18
- import { type InputComponent, type InputProps } from './Input';
19
-
20
- export type PropsFilter<T extends BaseObject> = (props: SchemaProperty<T>[]) => SchemaProperty<T>[];
21
-
22
- export type ComponentLookup = (args: {
23
- prop: string;
24
- schema: Schema.Schema<any>;
25
- inputProps: InputProps;
26
- }) => ReactElement | undefined;
27
-
28
- export type CustomInputMap = Partial<Record<string, InputComponent>>;
29
-
30
- export type FormProps<T extends BaseObject> = ThemedClassName<{
31
- values: Partial<T>;
32
- // TODO(burdon): Autofocus first input.
33
- autoFocus?: boolean;
34
- // TODO(burdon): Change to JsonPath includes/excludes.
35
- filter?: PropsFilter<T>;
36
- sort?: PropertyKey<T>[];
37
- autoSave?: boolean;
38
- outerSpacing?: FormOuterSpacing;
39
- onCancel?: () => void;
40
- }> &
41
- Pick<FormOptions<T>, 'schema' | 'onValuesChanged' | 'onValidate' | 'onSave'> &
42
- FormFieldsProps;
43
-
44
- export const Form = <T extends BaseObject>({
45
- classNames,
46
- testId,
47
- values: initialValues,
48
- autoFocus,
49
- readonly,
50
- autoSave,
51
- outerSpacing = true,
52
- onCancel,
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import * as Option from 'effect/Option';
7
+ import * as Schema from 'effect/Schema';
8
+ import * as SchemaAST from 'effect/SchemaAST';
9
+ import React, { type PropsWithChildren, useEffect, useMemo, useRef } from 'react';
10
+
11
+ import { Annotation as EchoAnnotation, Type } from '@dxos/echo';
12
+ import { type AnyProperties } from '@dxos/echo/internal';
13
+ import { SchemaEx } from '@dxos/effect';
14
+ import {
15
+ Column,
16
+ type ColumnRootProps,
17
+ IconButton,
18
+ type IconButtonProps,
19
+ Input,
20
+ ScrollArea,
21
+ type ThemedClassName,
22
+ useMergeRefs,
23
+ useTranslation,
24
+ } from '@dxos/react-ui';
25
+ import { composable, composableProps, withColumn } from '@dxos/react-ui';
26
+ import { mx } from '@dxos/ui-theme';
27
+
28
+ import { translationKey } from '#translations';
29
+
30
+ import {
31
+ type FormHandler,
32
+ type FormHandlerProps,
33
+ type FormUpdateMeta,
34
+ useFormHandler,
35
+ useKeyHandler,
36
+ } from '../../hooks';
37
+ import { FormFieldLabel, type FormFieldLabelProps, type FormFieldStateProps } from './FormFieldComponent';
38
+ import {
39
+ FormFieldSet as NaturalFormFieldSet,
40
+ type FormFieldSetProps as NaturalFormFieldSetProps,
41
+ } from './FormFieldSet';
42
+ import { FormTooltipsContext } from './FormTooltipsContext';
43
+ import { FormLayout as NaturalFormLayout } from './Layout';
44
+ import { type FormLayoutProps as NaturalFormLayoutProps } from './Layout/FormLayout';
45
+
46
+ // TODO(burdon): Move styles to form.ts (as with ui-theme).
47
+
48
+ // TODO(burdon): Reconcile with @dxos/echo.
49
+ export type ExcludeId<S extends Schema.Schema.AnyNoContext | Type.AnyEntity> = Omit<
50
+ S extends Type.AnyEntity
51
+ ? Type.InstanceType<S>
52
+ : S extends Schema.Schema.AnyNoContext
53
+ ? Schema.Schema.Type<S>
54
+ : never,
55
+ 'id'
56
+ >;
57
+
58
+ // TODO(burdon): Move to @dxos/schema (re-export here).
59
+ export const omitId = <S extends Schema.Schema.AnyNoContext | Type.AnyEntity>(
60
+ schemaOrType: S,
61
+ ): Schema.Schema<ExcludeId<S>, ExcludeId<S>> => {
62
+ const schema = Type.isType(schemaOrType)
63
+ ? Type.getSchema(schemaOrType)
64
+ : (schemaOrType as Schema.Schema.AnyNoContext);
65
+ return schema.pipe(Schema.omit('id')) as any;
66
+ };
67
+
68
+ /**
69
+ * Drop fields annotated with `FormInputAnnotation.set(false)` from a schema so
70
+ * the form's validator doesn't trip on required-but-hidden fields. Used by
71
+ * the picker's inline create form, where a `FactoryAnnotation` typically
72
+ * supplies the hidden values (e.g. a backing-object Ref) outside the form.
73
+ */
74
+ export const omitHiddenFormFields = <S extends Schema.Schema.AnyNoContext>(schema: S): S => {
75
+ const properties = SchemaAST.getPropertySignatures(schema.ast);
76
+ const hidden = properties
77
+ .filter((prop) => Option.getOrElse(EchoAnnotation.FormInputAnnotation.getFromAst(prop.type), () => true) === false)
78
+ .map((prop) => prop.name as string);
79
+ return hidden.length === 0 ? schema : (schema.pipe(Schema.omit(...(hidden as [string, ...string[]]))) as any);
80
+ };
81
+
82
+ //
83
+ // Context
84
+ //
85
+
86
+ type FormContextValue<T extends AnyProperties = any> = {
87
+ /**
88
+ * Form handler.
89
+ */
90
+ form: FormHandler<T>;
91
+
92
+ /**
93
+ * Show field tooltips (currently: JSON path on each label). Defaults to
94
+ * `true`; pass `false` to suppress.
95
+ */
96
+ tooltips?: boolean;
97
+
98
+ /**
99
+ * Testing.
100
+ */
101
+ testId?: string;
102
+ } & Pick<
103
+ NaturalFormFieldSetProps<T>,
104
+ 'readonly' | 'layout' | 'fieldMap' | 'fieldProvider' | 'projection' | 'createTypename' | 'createFieldMap' | 'db'
105
+ >;
106
+
107
+ const [FormContextProvider, useFormContext] = createContext<FormContextValue>('Form');
108
+
109
+ /**
110
+ * Get the current form values.
111
+ */
112
+ const useFormValues: {
113
+ <T extends AnyProperties>(componentName: string, path?: (string | number)[]): T;
114
+ <T extends AnyProperties>(
115
+ componentName: string,
116
+ path: (string | number)[] | undefined,
117
+ defaultValue: () => T,
118
+ ): T | undefined;
119
+ } = (componentName: string, path?: (string | number)[], defaultValue?: () => any) => {
120
+ const stablePath = useMemo(() => path ?? [], [path ? path.join('.') : undefined]);
121
+ const jsonPath = SchemaEx.createJsonPath(stablePath);
122
+ const {
123
+ form: { values, onValueChange },
124
+ } = useFormContext(componentName);
125
+
126
+ const value = SchemaEx.getValue(values, jsonPath);
127
+
128
+ // Apply default value once when the field has no value. lastAppliedPathRef prevents
129
+ // re-applying on every render (e.g. when defaultValue() returns null) and ensures
130
+ // we apply per path when the hook is used for different fields.
131
+ const lastAppliedPathRef = useRef<string | null>(null);
132
+ useEffect(() => {
133
+ if (value == null && defaultValue && lastAppliedPathRef.current !== jsonPath) {
134
+ lastAppliedPathRef.current = jsonPath;
135
+ onValueChange(stablePath, SchemaAST.stringKeyword, defaultValue());
136
+ }
137
+ }, [value, defaultValue, onValueChange, stablePath, jsonPath]);
138
+
139
+ return value;
140
+ };
141
+
142
+ /**
143
+ * Get the state props for the given field.
144
+ */
145
+ const useFormFieldState = (componentName: string, path: (string | number)[] = []): FormFieldStateProps => {
146
+ const stablePath = useMemo(() => path, [Array.isArray(path) ? path.join('.') : path]);
147
+ const {
148
+ form: { getStatus, getValue, onBlur, onValueChange },
149
+ } = useFormContext(componentName);
150
+
151
+ return useMemo(
152
+ () => ({
153
+ getStatus: () => getStatus(stablePath),
154
+ getValue: () => getValue(stablePath),
155
+ onBlur: () => onBlur(stablePath),
156
+ onValueChange: (ast: SchemaAST.AST, value: any) => onValueChange(stablePath, ast, value),
157
+ }),
158
+ [getStatus, getValue, onBlur, onValueChange, stablePath],
159
+ );
160
+ };
161
+
162
+ //
163
+ // Root
164
+ //
165
+
166
+ type FormRootProps<T extends AnyProperties = AnyProperties> = PropsWithChildren<
167
+ {
168
+ /**
169
+ * Called when the form is submitted and passes validation.
170
+ */
171
+ onSave?: (values: T, meta: FormUpdateMeta<T>) => void;
172
+
173
+ /**
174
+ * Called when the form is canceled to abandon/undo any pending changes.
175
+ */
176
+ onCancel?: () => void;
177
+ } & Omit<FormContextValue<T>, 'form'> &
178
+ Pick<FormHandlerProps<T>, 'schema' | 'autoSave' | 'values' | 'defaultValues' | 'onValidate' | 'onValuesChanged'> &
179
+ Omit<NaturalFormFieldSetProps<T>, 'schema' | 'path'>
180
+ >;
181
+
182
+ const FormRoot = <T extends AnyProperties = AnyProperties>({
183
+ children,
53
184
  schema,
54
- onValuesChanged,
55
- onValidate,
185
+ values,
56
186
  onSave,
187
+ onCancel,
57
188
  ...props
58
- }: FormProps<T>) => {
59
- const formRef = useRef<HTMLDivElement>(null);
189
+ }: FormRootProps<T>) => {
190
+ const form = useFormHandler({ schema, values, onSave, onCancel, ...props });
191
+
192
+ return (
193
+ <FormTooltipsContext.Provider value={props.tooltips ?? true}>
194
+ <FormContextProvider form={form} {...props}>
195
+ {children}
196
+ </FormContextProvider>
197
+ </FormTooltipsContext.Provider>
198
+ );
199
+ };
60
200
 
61
- // TODO(burdon): Rename.
62
- const handleValid = useMemo(() => (autoSave ? onSave : undefined), [autoSave, onSave]);
201
+ FormRoot.displayName = 'Form.Root';
63
202
 
64
- // Focus the first input element within this form.
65
- useEffect(() => {
66
- if (autoFocus && formRef.current) {
67
- const input = formRef.current.querySelector('input');
68
- if (input) {
69
- input.focus();
70
- }
203
+ //
204
+ // Viewport
205
+ //
206
+
207
+ const FORM_VIEWPORT_NAME = 'Form.Viewport';
208
+
209
+ type FormViewportProps = { scroll?: boolean; gutter?: ColumnRootProps['gutter'] };
210
+
211
+ // The viewing window: owns the gutter Column (chrome/side-padding).
212
+ // Content-height by default; `scroll` makes it fill its parent and scroll (the gutter then hosts the scrollbar).
213
+ const FormViewport = composable<HTMLDivElement, FormViewportProps>(
214
+ ({ children, scroll, gutter = 'xs', ...props }, forwardedRef) => {
215
+ // Span the full width when nested inside another Column grid (e.g. Card.Root)
216
+ // instead of landing in a single narrow track.
217
+ const span = '[.dx-column-root_&]:col-span-full';
218
+ if (scroll) {
219
+ return (
220
+ <Column.Root gutter={gutter} classNames={['dx-expander', span]}>
221
+ <ScrollArea.Root {...composableProps(props)} orientation='vertical' centered padding thin ref={forwardedRef}>
222
+ <ScrollArea.Viewport>{children}</ScrollArea.Viewport>
223
+ </ScrollArea.Root>
224
+ </Column.Root>
225
+ );
71
226
  }
72
- }, [autoFocus]);
227
+
228
+ return (
229
+ <Column.Root {...composableProps(props)} gutter={gutter} classNames={['w-full min-w-0', span]} ref={forwardedRef}>
230
+ {children}
231
+ </Column.Root>
232
+ );
233
+ },
234
+ );
235
+
236
+ FormViewport.displayName = FORM_VIEWPORT_NAME;
237
+
238
+ //
239
+ // Content
240
+ //
241
+
242
+ const FORM_CONTENT_NAME = 'Form.Content';
243
+
244
+ type FormContentProps = ThemedClassName<PropsWithChildren<{}>>;
245
+
246
+ // The viewed body: centered in the viewport's gutter. Pure body — the gutter Column is owned by `Form.Viewport`.
247
+ const FormContent = composable<HTMLDivElement, FormContentProps>(({ children, ...props }, forwardedRef) => {
248
+ const { form, testId } = useFormContext(FORM_CONTENT_NAME);
249
+ const localRef = useRef<HTMLDivElement>(null);
250
+ const mergedRef = useMergeRefs([forwardedRef, localRef]);
251
+ useKeyHandler(localRef, form);
252
+
253
+ return (
254
+ <div
255
+ {...composableProps(props, {
256
+ role: 'form',
257
+ classNames: mx(withColumn.center(), 'flex flex-col w-full'),
258
+ })}
259
+ data-testid={testId}
260
+ ref={mergedRef}
261
+ >
262
+ {children}
263
+ </div>
264
+ );
265
+ });
266
+
267
+ FormContent.displayName = FORM_CONTENT_NAME;
268
+
269
+ //
270
+ // FieldSet
271
+ //
272
+
273
+ const FORM_FIELDSET_NAME = 'Form.FieldSet';
274
+
275
+ type FormFieldSetProps = ThemedClassName<NaturalFormFieldSetProps<any>>;
276
+
277
+ const FormFieldSet = (props: FormFieldSetProps) => {
278
+ const { form, ...contextProps } = useFormContext(FORM_FIELDSET_NAME);
279
+
280
+ return <NaturalFormFieldSet schema={form.schema} {...contextProps} {...props} />;
281
+ };
282
+
283
+ FormFieldSet.displayName = FORM_FIELDSET_NAME;
284
+
285
+ //
286
+ // Layout
287
+ //
288
+
289
+ const FORM_LAYOUT_NAME = 'Form.Layout';
290
+
291
+ type FormLayoutProps = Omit<NaturalFormLayoutProps, 'schema'> & { schema?: NaturalFormLayoutProps['schema'] };
292
+
293
+ const FormLayout = ({ schema, ...props }: FormLayoutProps) => {
294
+ const { form, ...contextProps } = useFormContext(FORM_LAYOUT_NAME);
295
+ const resolvedSchema = schema ?? form.schema;
296
+ if (!resolvedSchema) {
297
+ return null;
298
+ }
299
+
300
+ return <NaturalFormLayout schema={resolvedSchema} {...contextProps} {...props} />;
301
+ };
302
+
303
+ FormLayout.displayName = FORM_LAYOUT_NAME;
304
+
305
+ //
306
+ // Actions
307
+ //
308
+
309
+ const FORM_ACTIONS_NAME = 'Form.Actions';
310
+
311
+ type FormActionsProps = ThemedClassName<{}>;
312
+
313
+ const FormActions = ({ classNames }: FormActionsProps) => {
314
+ const { t } = useTranslation(translationKey);
315
+ const {
316
+ form: { canSave, onSave, onCancel },
317
+ readonly,
318
+ layout,
319
+ } = useFormContext(FORM_ACTIONS_NAME);
320
+
321
+ if (readonly || layout === 'static') {
322
+ return null;
323
+ }
324
+
325
+ // TODO(burdon): Currently onCancel is a no-op; implement "revert values".
326
+ // Deprecate FormSubmit ans use FormActions without Cancel button if no callback is supplied.
73
327
 
74
328
  return (
75
- <FormProvider
76
- formRef={formRef}
77
- schema={schema}
78
- autoSave={autoSave}
79
- initialValues={initialValues}
80
- onValuesChanged={onValuesChanged}
81
- onValidate={onValidate}
82
- onValid={handleValid}
83
- onSave={onSave}
329
+ <div
330
+ className={mx(withColumn.center(), 'grid grid-flow-col gap-form-gap auto-cols-fr py-form-padding', classNames)}
84
331
  >
85
- <div role='none' className='contents' data-testid={testId}>
86
- <FormFields
87
- {...props}
88
- ref={formRef}
89
- classNames={[
90
- outerSpacing === 'blockStart-0'
91
- ? 'pli-cardSpacingInline mbe-cardSpacingBlock [&>.mbs-inputSpacingBlock:first-child]:!mbs-0'
92
- : outerSpacing === 'scroll-fields'
93
- ? 'pli-cardSpacingInline pbe-cardSpacingBlock'
94
- : outerSpacing
95
- ? cardSpacing
96
- : false,
97
- outerSpacing === 'scroll-fields' && cardDialogOverflow,
98
- classNames,
99
- ]}
100
- readonly={readonly}
101
- schema={schema}
332
+ {onCancel && (
333
+ <IconButton
334
+ icon='ph--x--regular'
335
+ iconEnd
336
+ label={t('cancel-button.label')}
337
+ onClick={onCancel}
338
+ data-testid='cancel-button'
339
+ />
340
+ )}
341
+ {onSave && (
342
+ <IconButton
343
+ type='submit'
344
+ variant='primary'
345
+ disabled={!canSave}
346
+ icon='ph--check--regular'
347
+ iconEnd
348
+ label={t('save-button.label')}
349
+ onClick={onSave}
350
+ data-testid='save-button'
102
351
  />
103
- {(onCancel || onSave) && !autoSave && !readonly && (
104
- <FormActions readonly={readonly} onCancel={onCancel} outerSpacing={outerSpacing} />
105
- )}
352
+ )}
353
+ </div>
354
+ );
355
+ };
356
+
357
+ FormActions.displayName = FORM_ACTIONS_NAME;
358
+
359
+ //
360
+ // Section
361
+ //
362
+
363
+ const FORM_SECTION_NAME = 'Form.Section';
364
+
365
+ type FormSectionProps = ThemedClassName<{ label?: string; description?: string }>;
366
+
367
+ const FormSection = composable<HTMLDivElement, FormSectionProps>(
368
+ ({ children, label, description, ...props }, forwardedRef) => {
369
+ return (
370
+ <div
371
+ {...composableProps(props, { classNames: 'flex flex-col pt-form-section-gap first:pt-0' })}
372
+ ref={forwardedRef}
373
+ >
374
+ {label && <h2 className='text-lg'>{label}</h2>}
375
+ {description && <p className='text-description'>{description}</p>}
376
+ {children}
106
377
  </div>
107
- </FormProvider>
378
+ );
379
+ },
380
+ );
381
+
382
+ FormSection.displayName = FORM_SECTION_NAME;
383
+
384
+ //
385
+ // Submit
386
+ //
387
+
388
+ const FORM_SUBMIT_NAME = 'Form.Submit';
389
+
390
+ type FormSubmitProps = ThemedClassName<Partial<Pick<IconButtonProps, 'icon' | 'label' | 'disabled'>>>;
391
+
392
+ const FormSubmit = ({ classNames, label, icon, disabled }: FormSubmitProps) => {
393
+ const { t } = useTranslation(translationKey);
394
+ const {
395
+ form: { canSave, onSave },
396
+ readonly,
397
+ layout,
398
+ } = useFormContext(FORM_SUBMIT_NAME);
399
+
400
+ if (readonly || layout === 'static') {
401
+ return null;
402
+ }
403
+
404
+ return (
405
+ <div className={mx('flex w-full pt-form-padding', classNames)}>
406
+ <IconButton
407
+ classNames='w-full'
408
+ type='submit'
409
+ variant='primary'
410
+ disabled={disabled ?? !canSave}
411
+ icon={icon ?? 'ph--check--regular'}
412
+ label={label ?? t('save-button.label')}
413
+ onClick={onSave}
414
+ data-testid='save-button'
415
+ />
416
+ </div>
108
417
  );
109
418
  };
419
+
420
+ FormSubmit.displayName = FORM_SUBMIT_NAME;
421
+
422
+ //
423
+ // Error
424
+ //
425
+
426
+ const FORM_ERROR_NAME = 'Form.Error';
427
+
428
+ type FormErrorProps = ThemedClassName<PropsWithChildren>;
429
+
430
+ /** Form-level error/validation message (e.g. a failed submit), styled via the error valence. */
431
+ const FormError = ({ children, classNames }: FormErrorProps) => {
432
+ if (!children) {
433
+ return null;
434
+ }
435
+
436
+ return (
437
+ <Input.Root validationValence='error'>
438
+ <Input.Validation classNames={classNames}>{children}</Input.Validation>
439
+ </Input.Root>
440
+ );
441
+ };
442
+
443
+ FormError.displayName = FORM_ERROR_NAME;
444
+
445
+ //
446
+ // Form
447
+ // https://www.radix-ui.com/primitives/docs/guides/composition
448
+ //
449
+
450
+ export const Form = {
451
+ Root: FormRoot,
452
+ Viewport: FormViewport,
453
+ Content: FormContent,
454
+ Section: FormSection,
455
+ FieldSet: FormFieldSet,
456
+ Layout: FormLayout,
457
+ Label: FormFieldLabel,
458
+ Actions: FormActions,
459
+ Submit: FormSubmit,
460
+ Error: FormError,
461
+ };
462
+
463
+ export { useFormContext, useFormValues, useFormFieldState };
464
+
465
+ export type {
466
+ FormRootProps,
467
+ FormViewportProps,
468
+ FormContentProps,
469
+ FormSectionProps,
470
+ FormFieldSetProps,
471
+ FormLayoutProps,
472
+ FormFieldLabelProps,
473
+ FormActionsProps,
474
+ FormSubmitProps,
475
+ };