@dxos/react-ui-form 0.9.0 → 0.9.1-staging.ee54ba693a

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 (372) hide show
  1. package/dist/lib/browser/index.mjs +2337 -1919
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +2337 -1919
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/annotations.d.ts +47 -0
  8. package/dist/types/src/annotations.d.ts.map +1 -0
  9. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +3 -3
  10. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  11. package/dist/types/src/components/Form/Form.d.ts +23 -110
  12. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  13. package/dist/types/src/components/Form/Form.stories.d.ts +48 -101
  14. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/Form/Form.theme.d.ts +252 -0
  16. package/dist/types/src/components/Form/Form.theme.d.ts.map +1 -0
  17. package/dist/types/src/components/Form/Form.theme.test.d.ts +2 -0
  18. package/dist/types/src/components/Form/Form.theme.test.d.ts.map +1 -0
  19. package/dist/types/src/components/Form/FormControls.d.ts +75 -0
  20. package/dist/types/src/components/Form/FormControls.d.ts.map +1 -0
  21. package/dist/types/src/components/Form/FormField/FormField.d.ts +44 -0
  22. package/dist/types/src/components/Form/FormField/FormField.d.ts.map +1 -0
  23. package/dist/types/src/components/Form/FormField/FormFieldHeader.d.ts +27 -0
  24. package/dist/types/src/components/Form/FormField/FormFieldHeader.d.ts.map +1 -0
  25. package/dist/types/src/components/Form/FormField/FormRow.d.ts +85 -0
  26. package/dist/types/src/components/Form/FormField/FormRow.d.ts.map +1 -0
  27. package/dist/types/src/components/Form/{FormFieldComponent.stories.d.ts → FormField/FormRow.stories.d.ts} +6 -3
  28. package/dist/types/src/components/Form/FormField/FormRow.stories.d.ts.map +1 -0
  29. package/dist/types/src/components/Form/{fields → FormField/fields/ArrayField}/ArrayField.d.ts +2 -2
  30. package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.d.ts.map +1 -0
  31. package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts +88 -0
  32. package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts +2 -0
  34. package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts.map +1 -0
  35. package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.d.ts +12 -0
  36. package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.d.ts.map +1 -0
  37. package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/index.d.ts +2 -0
  38. package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/index.d.ts.map +1 -0
  39. package/dist/types/src/components/Form/FormField/fields/AutofillField/AutofillField.d.ts +12 -0
  40. package/dist/types/src/components/Form/FormField/fields/AutofillField/AutofillField.d.ts.map +1 -0
  41. package/dist/types/src/components/Form/FormField/fields/AutofillField/index.d.ts +2 -0
  42. package/dist/types/src/components/Form/FormField/fields/AutofillField/index.d.ts.map +1 -0
  43. package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.d.ts +4 -0
  44. package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.d.ts.map +1 -0
  45. package/dist/types/src/components/{Settings/Settings.stories.d.ts → Form/FormField/fields/BooleanField/BooleanField.stories.d.ts} +1 -2
  46. package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.d.ts.map +1 -0
  47. package/dist/types/src/components/Form/FormField/fields/BooleanField/index.d.ts +2 -0
  48. package/dist/types/src/components/Form/FormField/fields/BooleanField/index.d.ts.map +1 -0
  49. package/dist/types/src/components/Form/FormField/fields/ComboboxField/ComboboxField.d.ts +12 -0
  50. package/dist/types/src/components/Form/FormField/fields/ComboboxField/ComboboxField.d.ts.map +1 -0
  51. package/dist/types/src/components/Form/FormField/fields/ComboboxField/index.d.ts +2 -0
  52. package/dist/types/src/components/Form/FormField/fields/ComboboxField/index.d.ts.map +1 -0
  53. package/dist/types/src/components/Form/FormField/fields/DateField/DateField.d.ts +4 -0
  54. package/dist/types/src/components/Form/FormField/fields/DateField/DateField.d.ts.map +1 -0
  55. package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts +88 -0
  56. package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/Form/FormField/fields/DateField/index.d.ts +2 -0
  58. package/dist/types/src/components/Form/FormField/fields/DateField/index.d.ts.map +1 -0
  59. package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.d.ts +5 -0
  60. package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.d.ts.map +1 -0
  61. package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts +88 -0
  62. package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts.map +1 -0
  63. package/dist/types/src/components/Form/FormField/fields/GeoPointField/index.d.ts +2 -0
  64. package/dist/types/src/components/Form/FormField/fields/GeoPointField/index.d.ts.map +1 -0
  65. package/dist/types/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.d.ts +2 -2
  66. package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.d.ts.map +1 -0
  67. package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.stories.d.ts.map +1 -0
  68. package/dist/types/src/components/Form/FormField/fields/MarkdownField/index.d.ts +2 -0
  69. package/dist/types/src/components/Form/FormField/fields/MarkdownField/index.d.ts.map +1 -0
  70. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts +15 -0
  71. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts.map +1 -0
  72. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts +88 -0
  73. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts.map +1 -0
  74. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.test.d.ts +2 -0
  75. package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.test.d.ts.map +1 -0
  76. package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts +2 -0
  77. package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts.map +1 -0
  78. package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.d.ts +4 -0
  79. package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.d.ts.map +1 -0
  80. package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts +88 -0
  81. package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts.map +1 -0
  82. package/dist/types/src/components/Form/FormField/fields/PasswordField/index.d.ts +2 -0
  83. package/dist/types/src/components/Form/FormField/fields/PasswordField/index.d.ts.map +1 -0
  84. package/dist/types/src/components/Form/FormField/fields/RefField/InlineRefField.d.ts.map +1 -0
  85. package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts +16 -0
  86. package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts.map +1 -0
  87. package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts +92 -0
  88. package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts.map +1 -0
  89. package/dist/types/src/components/Form/FormField/fields/RefField/RefField.test.d.ts.map +1 -0
  90. package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts +3 -0
  91. package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts.map +1 -0
  92. package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts +29 -0
  93. package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts.map +1 -0
  94. package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts +88 -0
  95. package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts.map +1 -0
  96. package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts +2 -0
  97. package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts.map +1 -0
  98. package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.d.ts +5 -0
  99. package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.d.ts.map +1 -0
  100. package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.stories.d.ts.map +1 -0
  101. package/dist/types/src/components/Form/FormField/fields/SelectOptionField/index.d.ts +2 -0
  102. package/dist/types/src/components/Form/FormField/fields/SelectOptionField/index.d.ts.map +1 -0
  103. package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.d.ts +4 -0
  104. package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.d.ts.map +1 -0
  105. package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts +88 -0
  106. package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts.map +1 -0
  107. package/dist/types/src/components/Form/FormField/fields/TextAreaField/index.d.ts +2 -0
  108. package/dist/types/src/components/Form/FormField/fields/TextAreaField/index.d.ts.map +1 -0
  109. package/dist/types/src/components/Form/FormField/fields/TextField/TextField.d.ts +4 -0
  110. package/dist/types/src/components/Form/FormField/fields/TextField/TextField.d.ts.map +1 -0
  111. package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts +88 -0
  112. package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts.map +1 -0
  113. package/dist/types/src/components/Form/FormField/fields/TextField/index.d.ts +2 -0
  114. package/dist/types/src/components/Form/FormField/fields/TextField/index.d.ts.map +1 -0
  115. package/dist/types/src/components/Form/{fields → FormField/fields/TupleField}/TupleField.d.ts +2 -2
  116. package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.d.ts.map +1 -0
  117. package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts +88 -0
  118. package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts.map +1 -0
  119. package/dist/types/src/components/Form/FormField/fields/TupleField/index.d.ts +2 -0
  120. package/dist/types/src/components/Form/FormField/fields/TupleField/index.d.ts.map +1 -0
  121. package/dist/types/src/components/Form/{fields → FormField/fields}/index.d.ts +4 -1
  122. package/dist/types/src/components/Form/FormField/fields/index.d.ts.map +1 -0
  123. package/dist/types/src/components/Form/FormField/index.d.ts +6 -0
  124. package/dist/types/src/components/Form/FormField/index.d.ts.map +1 -0
  125. package/dist/types/src/components/Form/FormField/presentation.d.ts +22 -0
  126. package/dist/types/src/components/Form/FormField/presentation.d.ts.map +1 -0
  127. package/dist/types/src/components/Form/FormFieldSet/FormFieldSet.d.ts +30 -0
  128. package/dist/types/src/components/Form/FormFieldSet/FormFieldSet.d.ts.map +1 -0
  129. package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts +22 -0
  130. package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts.map +1 -0
  131. package/dist/types/src/components/Form/FormFieldSet/index.d.ts +3 -0
  132. package/dist/types/src/components/Form/FormFieldSet/index.d.ts.map +1 -0
  133. package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.d.ts +2 -0
  134. package/dist/types/src/components/Form/FormLayout/FormLayout.d.ts.map +1 -0
  135. package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.stories.d.ts +5 -5
  136. package/dist/types/src/components/Form/FormLayout/FormLayout.stories.d.ts.map +1 -0
  137. package/dist/types/src/components/Form/FormLayout/FormLayout.stories.test.d.ts.map +1 -0
  138. package/dist/types/src/components/Form/FormLayout/FormLayout.test.d.ts.map +1 -0
  139. package/dist/types/src/components/Form/FormLayout/index.d.ts +3 -0
  140. package/dist/types/src/components/Form/FormLayout/index.d.ts.map +1 -0
  141. package/dist/types/src/components/Form/FormLayout/parser.d.ts.map +1 -0
  142. package/dist/types/src/components/Form/FormLayout/parser.test.d.ts.map +1 -0
  143. package/dist/types/src/components/Form/index.d.ts +3 -5
  144. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  145. package/dist/types/src/components/Form/meta-tags.d.ts +1 -12
  146. package/dist/types/src/components/Form/meta-tags.d.ts.map +1 -1
  147. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -1
  148. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +6 -23
  149. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
  150. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +2 -1
  151. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -1
  152. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts +2 -2
  153. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts.map +1 -1
  154. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +1 -1
  155. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  156. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +2 -2
  157. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  158. package/dist/types/src/components/index.d.ts +0 -1
  159. package/dist/types/src/components/index.d.ts.map +1 -1
  160. package/dist/types/src/hooks/index.d.ts +2 -0
  161. package/dist/types/src/hooks/index.d.ts.map +1 -1
  162. package/dist/types/src/hooks/useAsyncFieldEffect.d.ts +24 -0
  163. package/dist/types/src/hooks/useAsyncFieldEffect.d.ts.map +1 -0
  164. package/dist/types/src/hooks/useFormContext.d.ts +42 -0
  165. package/dist/types/src/hooks/useFormContext.d.ts.map +1 -0
  166. package/dist/types/src/hooks/useFormHandler.d.ts +9 -6
  167. package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
  168. package/dist/types/src/index.d.ts +2 -0
  169. package/dist/types/src/index.d.ts.map +1 -1
  170. package/dist/types/src/{components/testing.d.ts → testing/TestLayout.d.ts} +2 -2
  171. package/dist/types/src/testing/TestLayout.d.ts.map +1 -0
  172. package/dist/types/src/testing/index.d.ts +3 -0
  173. package/dist/types/src/testing/index.d.ts.map +1 -0
  174. package/dist/types/src/testing/schema.d.ts +40 -0
  175. package/dist/types/src/testing/schema.d.ts.map +1 -0
  176. package/dist/types/src/types.d.ts +161 -0
  177. package/dist/types/src/types.d.ts.map +1 -0
  178. package/dist/types/src/util/index.d.ts +1 -1
  179. package/dist/types/src/util/index.d.ts.map +1 -1
  180. package/dist/types/src/util/omit.d.ts +12 -0
  181. package/dist/types/src/util/omit.d.ts.map +1 -0
  182. package/dist/types/tsconfig.tsbuildinfo +1 -1
  183. package/package.json +43 -41
  184. package/src/annotations.ts +63 -0
  185. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  186. package/src/components/FieldEditor/FieldEditor.test.tsx +1 -1
  187. package/src/components/FieldEditor/FieldEditor.tsx +10 -6
  188. package/src/components/Form/DESIGN.md +24 -0
  189. package/src/components/Form/Form.stories.tsx +260 -61
  190. package/src/components/Form/Form.theme.test.ts +33 -0
  191. package/src/components/Form/Form.theme.ts +86 -0
  192. package/src/components/Form/Form.tsx +30 -453
  193. package/src/components/Form/FormControls.tsx +377 -0
  194. package/src/components/Form/{FormField.tsx → FormField/FormField.tsx} +98 -71
  195. package/src/components/Form/FormField/FormFieldHeader.tsx +68 -0
  196. package/src/components/Form/FormField/FormRow.stories.tsx +97 -0
  197. package/src/components/Form/FormField/FormRow.tsx +298 -0
  198. package/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.tsx +119 -0
  199. package/src/components/Form/FormField/fields/ArrayField/ArrayField.tsx +328 -0
  200. package/src/components/Form/FormField/fields/ArrayField/index.ts +5 -0
  201. package/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.tsx +59 -0
  202. package/src/components/Form/FormField/fields/AsyncSelectField/index.ts +5 -0
  203. package/src/components/Form/FormField/fields/AutofillField/AutofillField.tsx +67 -0
  204. package/src/components/Form/FormField/fields/AutofillField/index.ts +5 -0
  205. package/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.tsx +52 -0
  206. package/src/components/Form/FormField/fields/BooleanField/BooleanField.tsx +28 -0
  207. package/src/components/Form/FormField/fields/BooleanField/index.ts +5 -0
  208. package/src/components/Form/FormField/fields/ComboboxField/ComboboxField.tsx +104 -0
  209. package/src/components/Form/FormField/fields/ComboboxField/index.ts +5 -0
  210. package/src/components/Form/FormField/fields/DateField/DateField.stories.tsx +60 -0
  211. package/src/components/Form/{fields → FormField/fields/DateField}/DateField.tsx +12 -10
  212. package/src/components/Form/FormField/fields/DateField/index.ts +5 -0
  213. package/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.tsx +53 -0
  214. package/src/components/Form/{fields → FormField/fields/GeoPointField}/GeoPointField.tsx +19 -21
  215. package/src/components/Form/FormField/fields/GeoPointField/index.ts +5 -0
  216. package/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.stories.tsx +8 -8
  217. package/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.tsx +41 -41
  218. package/src/components/Form/FormField/fields/MarkdownField/index.ts +5 -0
  219. package/src/components/Form/FormField/fields/NumberField/NumberField.stories.tsx +52 -0
  220. package/src/components/Form/FormField/fields/NumberField/NumberField.test.ts +29 -0
  221. package/src/components/Form/FormField/fields/NumberField/NumberField.tsx +140 -0
  222. package/src/components/Form/FormField/fields/NumberField/index.ts +5 -0
  223. package/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.tsx +53 -0
  224. package/src/components/Form/FormField/fields/PasswordField/PasswordField.tsx +41 -0
  225. package/src/components/Form/FormField/fields/PasswordField/index.ts +5 -0
  226. package/src/components/Form/{fields → FormField/fields/RefField}/InlineRefField.tsx +21 -14
  227. package/src/components/Form/FormField/fields/RefField/RefField.stories.tsx +97 -0
  228. package/src/components/Form/{fields → FormField/fields/RefField}/RefField.test.ts +10 -1
  229. package/src/components/Form/{fields → FormField/fields/RefField}/RefField.tsx +55 -47
  230. package/src/components/Form/FormField/fields/RefField/index.ts +6 -0
  231. package/src/components/Form/FormField/fields/SelectField/SelectField.stories.tsx +53 -0
  232. package/src/components/Form/FormField/fields/SelectField/SelectField.tsx +136 -0
  233. package/src/components/Form/FormField/fields/SelectField/index.ts +5 -0
  234. package/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.stories.tsx +5 -5
  235. package/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.tsx +56 -54
  236. package/src/components/Form/FormField/fields/SelectOptionField/index.ts +5 -0
  237. package/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.tsx +53 -0
  238. package/src/components/Form/{fields → FormField/fields/TextAreaField}/TextAreaField.tsx +6 -4
  239. package/src/components/Form/FormField/fields/TextAreaField/index.ts +5 -0
  240. package/src/components/Form/FormField/fields/TextField/TextField.stories.tsx +52 -0
  241. package/src/components/Form/{fields → FormField/fields/TextField}/TextField.tsx +6 -4
  242. package/src/components/Form/FormField/fields/TextField/index.ts +5 -0
  243. package/src/components/Form/FormField/fields/TupleField/TupleField.stories.tsx +55 -0
  244. package/src/components/Form/{fields → FormField/fields/TupleField}/TupleField.tsx +4 -2
  245. package/src/components/Form/FormField/fields/TupleField/index.ts +5 -0
  246. package/src/components/Form/{fields → FormField/fields}/index.ts +4 -1
  247. package/src/components/Form/FormField/index.ts +10 -0
  248. package/src/components/Form/FormField/presentation.tsx +32 -0
  249. package/src/components/Form/{FormFieldSet.tsx → FormFieldSet/FormFieldSet.tsx} +53 -90
  250. package/src/components/Form/FormFieldSet/FormFieldSetContainer.tsx +93 -0
  251. package/src/components/Form/FormFieldSet/index.ts +6 -0
  252. package/src/components/Form/{Layout → FormLayout}/FormLayout.stories.tsx +11 -9
  253. package/src/components/Form/{Layout → FormLayout}/FormLayout.tsx +29 -18
  254. package/src/components/Form/FormLayout/index.ts +6 -0
  255. package/src/components/Form/index.ts +3 -5
  256. package/src/components/Form/meta-tags.test.ts +1 -1
  257. package/src/components/Form/meta-tags.ts +1 -1
  258. package/src/components/ObjectForm/ObjectForm.tsx +15 -14
  259. package/src/components/ObjectPicker/ObjectPicker.tsx +20 -27
  260. package/src/components/ObjectProperties/ObjectProperties.stories.tsx +2 -2
  261. package/src/components/ObjectProperties/ObjectProperties.test.tsx +1 -1
  262. package/src/components/ObjectProperties/ObjectProperties.tsx +13 -8
  263. package/src/components/RefEditor/RefEditor.stories.tsx +2 -3
  264. package/src/components/RefEditor/RefEditor.tsx +1 -1
  265. package/src/components/ViewEditor/ViewEditor.stories.tsx +6 -7
  266. package/src/components/ViewEditor/ViewEditor.test.tsx +9 -3
  267. package/src/components/ViewEditor/ViewEditor.tsx +98 -128
  268. package/src/components/index.ts +0 -1
  269. package/src/hooks/index.ts +2 -0
  270. package/src/hooks/useAsyncFieldEffect.ts +81 -0
  271. package/src/hooks/useFormContext.ts +89 -0
  272. package/src/hooks/useFormHandler.ts +12 -10
  273. package/src/index.ts +2 -0
  274. package/src/{components/testing.tsx → testing/TestLayout.tsx} +16 -13
  275. package/src/testing/index.ts +7 -0
  276. package/src/testing/schema.ts +59 -0
  277. package/src/types.ts +186 -0
  278. package/src/util/index.ts +1 -1
  279. package/src/util/omit.ts +61 -0
  280. package/src/util/properties.test.ts +110 -28
  281. package/src/util/refs.ts +1 -1
  282. package/src/vitest-setup.ts +40 -0
  283. package/dist/types/src/components/Form/FormField.d.ts +0 -52
  284. package/dist/types/src/components/Form/FormField.d.ts.map +0 -1
  285. package/dist/types/src/components/Form/FormFieldComponent.d.ts +0 -98
  286. package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +0 -1
  287. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +0 -1
  288. package/dist/types/src/components/Form/FormFieldSet.d.ts +0 -26
  289. package/dist/types/src/components/Form/FormFieldSet.d.ts.map +0 -1
  290. package/dist/types/src/components/Form/FormTooltipsContext.d.ts +0 -19
  291. package/dist/types/src/components/Form/FormTooltipsContext.d.ts.map +0 -1
  292. package/dist/types/src/components/Form/Layout/FormLayout.d.ts.map +0 -1
  293. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts.map +0 -1
  294. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts.map +0 -1
  295. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts.map +0 -1
  296. package/dist/types/src/components/Form/Layout/annotation.d.ts +0 -30
  297. package/dist/types/src/components/Form/Layout/annotation.d.ts.map +0 -1
  298. package/dist/types/src/components/Form/Layout/index.d.ts +0 -4
  299. package/dist/types/src/components/Form/Layout/index.d.ts.map +0 -1
  300. package/dist/types/src/components/Form/Layout/parser.d.ts.map +0 -1
  301. package/dist/types/src/components/Form/Layout/parser.test.d.ts.map +0 -1
  302. package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +0 -1
  303. package/dist/types/src/components/Form/fields/BooleanField.d.ts +0 -4
  304. package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +0 -1
  305. package/dist/types/src/components/Form/fields/DateField.d.ts +0 -4
  306. package/dist/types/src/components/Form/fields/DateField.d.ts.map +0 -1
  307. package/dist/types/src/components/Form/fields/GeoPointField.d.ts +0 -5
  308. package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +0 -1
  309. package/dist/types/src/components/Form/fields/InlineRefField.d.ts.map +0 -1
  310. package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +0 -1
  311. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +0 -1
  312. package/dist/types/src/components/Form/fields/NumberField.d.ts +0 -4
  313. package/dist/types/src/components/Form/fields/NumberField.d.ts.map +0 -1
  314. package/dist/types/src/components/Form/fields/RefField.d.ts +0 -34
  315. package/dist/types/src/components/Form/fields/RefField.d.ts.map +0 -1
  316. package/dist/types/src/components/Form/fields/RefField.test.d.ts.map +0 -1
  317. package/dist/types/src/components/Form/fields/SelectField.d.ts +0 -13
  318. package/dist/types/src/components/Form/fields/SelectField.d.ts.map +0 -1
  319. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +0 -5
  320. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +0 -1
  321. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +0 -1
  322. package/dist/types/src/components/Form/fields/TextAreaField.d.ts +0 -4
  323. package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +0 -1
  324. package/dist/types/src/components/Form/fields/TextField.d.ts +0 -4
  325. package/dist/types/src/components/Form/fields/TextField.d.ts.map +0 -1
  326. package/dist/types/src/components/Form/fields/TupleField.d.ts.map +0 -1
  327. package/dist/types/src/components/Form/fields/index.d.ts.map +0 -1
  328. package/dist/types/src/components/Settings/Settings.d.ts +0 -51
  329. package/dist/types/src/components/Settings/Settings.d.ts.map +0 -1
  330. package/dist/types/src/components/Settings/Settings.stories.d.ts.map +0 -1
  331. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +0 -43
  332. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +0 -1
  333. package/dist/types/src/components/Settings/SettingsItem.d.ts +0 -16
  334. package/dist/types/src/components/Settings/SettingsItem.d.ts.map +0 -1
  335. package/dist/types/src/components/Settings/SettingsSelectField.d.ts +0 -18
  336. package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +0 -1
  337. package/dist/types/src/components/Settings/index.d.ts +0 -4
  338. package/dist/types/src/components/Settings/index.d.ts.map +0 -1
  339. package/dist/types/src/components/testing.d.ts.map +0 -1
  340. package/dist/types/src/util/field-type.d.ts +0 -19
  341. package/dist/types/src/util/field-type.d.ts.map +0 -1
  342. package/src/components/Form/AUDIT.md +0 -17
  343. package/src/components/Form/FormFieldComponent.stories.tsx +0 -65
  344. package/src/components/Form/FormFieldComponent.tsx +0 -253
  345. package/src/components/Form/FormTooltipsContext.ts +0 -25
  346. package/src/components/Form/Layout/annotation.ts +0 -38
  347. package/src/components/Form/Layout/index.ts +0 -7
  348. package/src/components/Form/README.md +0 -3
  349. package/src/components/Form/fields/ArrayField.tsx +0 -173
  350. package/src/components/Form/fields/BooleanField.tsx +0 -22
  351. package/src/components/Form/fields/NumberField.tsx +0 -76
  352. package/src/components/Form/fields/SelectField.tsx +0 -77
  353. package/src/components/Settings/AUDIT.md +0 -51
  354. package/src/components/Settings/Settings.stories.tsx +0 -104
  355. package/src/components/Settings/Settings.tsx +0 -81
  356. package/src/components/Settings/SettingsFieldSet.tsx +0 -257
  357. package/src/components/Settings/SettingsItem.tsx +0 -58
  358. package/src/components/Settings/SettingsSelectField.tsx +0 -59
  359. package/src/components/Settings/index.ts +0 -7
  360. package/src/util/field-type.ts +0 -60
  361. /package/dist/types/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.stories.d.ts +0 -0
  362. /package/dist/types/src/components/Form/{fields → FormField/fields/RefField}/InlineRefField.d.ts +0 -0
  363. /package/dist/types/src/components/Form/{fields → FormField/fields/RefField}/RefField.test.d.ts +0 -0
  364. /package/dist/types/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.stories.d.ts +0 -0
  365. /package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.stories.test.d.ts +0 -0
  366. /package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.test.d.ts +0 -0
  367. /package/dist/types/src/components/Form/{Layout → FormLayout}/parser.d.ts +0 -0
  368. /package/dist/types/src/components/Form/{Layout → FormLayout}/parser.test.d.ts +0 -0
  369. /package/src/components/Form/{Layout → FormLayout}/FormLayout.stories.test.tsx +0 -0
  370. /package/src/components/Form/{Layout → FormLayout}/FormLayout.test.ts +0 -0
  371. /package/src/components/Form/{Layout → FormLayout}/parser.test.ts +0 -0
  372. /package/src/components/Form/{Layout → FormLayout}/parser.ts +0 -0
@@ -5,39 +5,31 @@
5
5
  import type * as Schema from 'effect/Schema';
6
6
  import React, { type KeyboardEvent, forwardRef, useCallback, useState } from 'react';
7
7
 
8
- import { type Palette, Popover, type ThemedClassName, useTranslation } from '@dxos/react-ui';
8
+ import { Popover, type ThemedClassName, useTranslation } from '@dxos/react-ui';
9
9
  import { Combobox } from '@dxos/react-ui-list';
10
10
  import { useSearchListResults } from '@dxos/react-ui-search';
11
11
 
12
12
  import { translationKey } from '#translations';
13
+ import { type CreateOptions, type RefOption } from '#types';
13
14
 
14
15
  import { Form } from '../Form';
15
- import { type FormFieldMap } from '../Form/FormFieldComponent';
16
16
 
17
- export type RefOption = {
18
- id: string;
19
- label: string;
20
- hue?: Palette;
21
- };
22
-
23
- export type ObjectPickerContentProps = ThemedClassName<{
24
- options: RefOption[];
25
- selectedIds?: string[];
26
- createOptionLabel?: [string, { ns: string | readonly string[] }];
27
- createOptionIcon?: string;
28
- createSchema?: Schema.Schema.AnyNoContext;
29
- createInitialValuePath?: string;
30
- createFieldMap?: FormFieldMap;
31
- /**
32
- * Persist a newly-created object given the form values. May be async (e.g.
33
- * to write to a database). The Promise is awaited before the inline create
34
- * form is collapsed back to the picker list, so consumers can complete
35
- * follow-up work (assign the new ref to a parent slot, close the popover)
36
- * before the picker UI re-renders.
37
- */
38
- onCreate?: (values: any) => unknown | Promise<unknown>;
39
- onSelect: (id: string) => void;
40
- }>;
17
+ export type ObjectPickerContentProps = ThemedClassName<
18
+ CreateOptions & {
19
+ options: RefOption[];
20
+ selectedIds?: string[];
21
+ createSchema?: Schema.Schema.AnyNoContext;
22
+ /**
23
+ * Persist a newly-created object given the form values. May be async (e.g.
24
+ * to write to a database). The Promise is awaited before the inline create
25
+ * form is collapsed back to the picker list, so consumers can complete
26
+ * follow-up work (assign the new ref to a parent slot, close the popover)
27
+ * before the picker UI re-renders.
28
+ */
29
+ onCreate?: (values: any) => unknown | Promise<unknown>;
30
+ onSelect?: (id: string) => void;
31
+ }
32
+ >;
41
33
 
42
34
  const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>(
43
35
  (
@@ -137,8 +129,9 @@ const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>
137
129
  key={option.id}
138
130
  value={option.id}
139
131
  label={option.label}
132
+ description={option.description}
140
133
  checked={selectedIds?.includes(option.id)}
141
- onSelect={() => onSelect(option.id)}
134
+ onSelect={() => onSelect?.(option.id)}
142
135
  classNames='flex items-center gap-2'
143
136
  />
144
137
  ))}
@@ -7,7 +7,7 @@ import * as Schema from 'effect/Schema';
7
7
  import React, { useEffect } from 'react';
8
8
  import { expect, userEvent, within } from 'storybook/test';
9
9
 
10
- import { DXN, Annotation, Filter, Obj, Ref, Tag, Type } from '@dxos/echo';
10
+ import { Annotation, DXN, Filter, Obj, Ref, Tag, Type } from '@dxos/echo';
11
11
  import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';
12
12
  import { useQuery } from '@dxos/react-client/echo';
13
13
  import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
@@ -18,7 +18,7 @@ import { Pipeline } from '@dxos/types';
18
18
 
19
19
  import { translations } from '#translations';
20
20
 
21
- import { OBJECT_PROPERTIES_DEBUG_SYMBOL } from '../testing';
21
+ import { OBJECT_PROPERTIES_DEBUG_SYMBOL } from '../../testing';
22
22
  import { ObjectProperties } from './ObjectProperties';
23
23
 
24
24
  //
@@ -9,7 +9,7 @@ import { afterEach, describe, expect, test } from 'vitest';
9
9
  import { Filter, Obj, Tag } from '@dxos/echo';
10
10
  import { DXN, EID } from '@dxos/keys';
11
11
 
12
- import { OBJECT_PROPERTIES_DEBUG_SYMBOL } from '../testing';
12
+ import { OBJECT_PROPERTIES_DEBUG_SYMBOL } from '../../testing';
13
13
  import * as stories from './ObjectProperties.stories';
14
14
  import { type ObjectPropertiesDebug } from './ObjectProperties.stories';
15
15
 
@@ -15,14 +15,17 @@ import { HuePicker } from '@dxos/react-ui-pickers';
15
15
  import { FactoryAnnotation } from '@dxos/schema';
16
16
 
17
17
  import { translationKey } from '#translations';
18
+ import { type FormFieldMap, type RefFieldDataProps } from '#types';
18
19
 
19
- import { Form, type FormFieldMap, META_TAGS_KEY, withMetaTags } from '../Form';
20
+ import { Form, META_TAGS_KEY, withMetaTags } from '../Form';
20
21
 
21
- export type ObjectPropertiesProps = PropsWithChildren<{ object: Obj.Unknown }>;
22
+ export type ObjectPropertiesProps = PropsWithChildren<
23
+ { object: Obj.Unknown } & Pick<RefFieldDataProps, 'getCreateDefaults' | 'resolveCreateEntry'>
24
+ >;
22
25
 
23
26
  // TODO(wittjosiah): Reconcile w/ ObjectForm.
24
27
  export const ObjectProperties = composable<HTMLDivElement, ObjectPropertiesProps>(
25
- ({ children, object, ...props }, forwardedRef) => {
28
+ ({ children, object, getCreateDefaults, resolveCreateEntry, ...props }, forwardedRef) => {
26
29
  const db = Obj.getDatabase(object);
27
30
  const meta = Obj.getMeta(object);
28
31
  // `meta.tags` already holds `Ref<Tag>`s (materialized by the database handler).
@@ -110,6 +113,7 @@ export const ObjectProperties = composable<HTMLDivElement, ObjectPropertiesProps
110
113
 
111
114
  return (
112
115
  <Form.Root
116
+ db={db}
113
117
  schema={formSchema}
114
118
  defaultValues={values as any}
115
119
  createTypename={Type.getTypename(Tag.Tag)}
@@ -117,14 +121,15 @@ export const ObjectProperties = composable<HTMLDivElement, ObjectPropertiesProps
117
121
  createOptionLabel={['add-tag.label', { ns: translationKey }]}
118
122
  createInitialValuePath='label'
119
123
  createFieldMap={createFieldMap}
120
- db={db}
121
124
  onValuesChanged={handleChange}
122
125
  onCreate={handleCreate}
126
+ getCreateDefaults={getCreateDefaults}
127
+ resolveCreateEntry={resolveCreateEntry}
123
128
  >
124
- <Form.Viewport {...composableProps(props)} ref={forwardedRef}>
129
+ <Form.Viewport {...composableProps(props)} scroll ref={forwardedRef}>
125
130
  <Form.Content>
126
131
  <Form.FieldSet />
127
- {children}
132
+ <Form.Section>{children}</Form.Section>
128
133
  </Form.Content>
129
134
  </Form.Viewport>
130
135
  </Form.Root>
@@ -133,12 +138,12 @@ export const ObjectProperties = composable<HTMLDivElement, ObjectPropertiesProps
133
138
  );
134
139
 
135
140
  const createFieldMap: FormFieldMap = {
136
- hue: ({ type, label, layout, getValue, onValueChange }) => {
141
+ hue: ({ type, label, presentation, getValue, onValueChange }) => {
137
142
  const handleChange = useCallback((nextHue: string) => onValueChange(type, nextHue), [onValueChange, type]);
138
143
  const handleReset = useCallback(() => onValueChange(type, undefined), [onValueChange, type]);
139
144
  return (
140
145
  <>
141
- {layout !== 'inline' && <Form.Label label={label} />}
146
+ {presentation !== 'inline' && <Form.Label label={label} />}
142
147
  <HuePicker value={getValue()} onChange={handleChange} onReset={handleReset} />
143
148
  </>
144
149
  );
@@ -69,11 +69,11 @@ const PeopleGrid = ({ db }: { db?: Database.Database }) => {
69
69
  );
70
70
  };
71
71
 
72
- type StoryProps = Partial<Pick<RefEditorProps, 'value' | 'mode' | 'activateOnTyping' | 'autoFocus'>>;
72
+ type StoryArgs = Partial<Pick<RefEditorProps, 'value' | 'mode' | 'activateOnTyping' | 'autoFocus'>>;
73
73
 
74
74
  // NOTE: The Person config (type/match/getValues) is supplied in render, not args — Storybook's
75
75
  // arg traversal attempts to mutate the proxied ECHO schema and crashes.
76
- const DefaultStory = ({ value: initialValue, ...args }: StoryProps) => {
76
+ const DefaultStory = ({ value: initialValue, ...args }: StoryArgs) => {
77
77
  const { space } = useClientStory();
78
78
  const [value, setValue] = useState(initialValue ?? '');
79
79
 
@@ -88,7 +88,6 @@ const DefaultStory = ({ value: initialValue, ...args }: StoryProps) => {
88
88
  icon='ph--user--regular'
89
89
  db={space?.db}
90
90
  onChange={setValue}
91
- classNames='border'
92
91
  />
93
92
  <JsonHighlighter data={{ value }} classNames='text-xs' />
94
93
  <PeopleGrid db={space?.db} />
@@ -246,7 +246,7 @@ export const RefEditor = forwardRef<EditorController, RefEditorProps>(
246
246
  >
247
247
  <Editor.View
248
248
  // TOOD(burdon): Use same style as react-ui Input.
249
- classNames='border border-separator rounded-xs px-2'
249
+ classNames='border border-input-separator rounded-xs px-2'
250
250
  {...props}
251
251
  initialValue={value}
252
252
  selectionEnd
@@ -12,17 +12,16 @@ import { type Mutable } from '@dxos/echo/Obj';
12
12
  import { useQuery } from '@dxos/react-client/echo';
13
13
  import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
14
14
  import { useAsyncEffect } from '@dxos/react-ui';
15
- import { withLayout, withTheme } from '@dxos/react-ui/testing';
15
+ import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
16
16
  import { type ProjectionModel, ViewModel, getTypeURIFromQuery } from '@dxos/schema';
17
17
  import { Employer, Organization, Person, Pipeline } from '@dxos/types';
18
18
 
19
19
  import { translations } from '#translations';
20
20
 
21
- import { TestLayout, VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
21
+ import { TestLayout, VIEW_EDITOR_DEBUG_SYMBOL } from '../../testing';
22
22
  import { ViewEditor, type ViewEditorProps } from './ViewEditor';
23
23
 
24
24
  const types = [
25
- // TODO(burdon): Get label from annotation.
26
25
  { value: Type.getURI(Organization.Organization), label: 'Organization' },
27
26
  { value: Type.getURI(Person.Person), label: 'Person' },
28
27
  { value: Type.getURI(Pipeline.Pipeline), label: 'Project' },
@@ -36,9 +35,9 @@ export type ViewEditorDebugObjects = {
36
35
  projection: ProjectionModel;
37
36
  };
38
37
 
39
- type DefaultStoryProps = Pick<ViewEditorProps, 'readonly' | 'mode'>;
38
+ type StoryArgs = Pick<ViewEditorProps, 'readonly' | 'mode'>;
40
39
 
41
- const DefaultStory = (props: DefaultStoryProps) => {
40
+ const DefaultStory = (props: StoryArgs) => {
42
41
  const { space } = useClientStory();
43
42
  const [type, setType] = useState<Type.AnyEntity>();
44
43
  const [view, setView] = useState<View.View>();
@@ -126,14 +125,14 @@ const DefaultStory = (props: DefaultStoryProps) => {
126
125
  }
127
126
  }, [type, view]);
128
127
 
129
- // NOTE(ZaymonFC): This looks awkward but it resolves an infinite parsing issue with sb.
128
+ // NOTE(ZaymonFC): Avoids infinite parsing issue with storybook args.
130
129
  const json = useMemo(
131
130
  () => JSON.parse(JSON.stringify({ schema: type, view, projection: projectionRef.current })),
132
131
  [JSON.stringify(type), JSON.stringify(view)],
133
132
  );
134
133
 
135
134
  if (!type || !view) {
136
- return <div />;
135
+ return <Loading />;
137
136
  }
138
137
 
139
138
  return (
@@ -10,7 +10,7 @@ import { Type, View } from '@dxos/echo';
10
10
  import { instanceOf as isInstanceOf } from '@dxos/echo/Obj';
11
11
  import { ProjectionModel } from '@dxos/schema';
12
12
 
13
- import { VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
13
+ import { VIEW_EDITOR_DEBUG_SYMBOL } from '../../testing';
14
14
  import * as stories from './ViewEditor.stories';
15
15
  import { type ViewEditorDebugObjects } from './ViewEditor.stories';
16
16
 
@@ -138,11 +138,17 @@ describe('ViewEditor', () => {
138
138
  expect(addedPropertyProjection!.props.property).toBe('added_property');
139
139
  });
140
140
 
141
- // TODO(mykola): Fix flaky test.
142
- test('delete property', { retry: 2 }, async () => {
141
+ test('delete property', async () => {
143
142
  await Default.run();
144
143
  await waitForViewEditor();
145
144
 
145
+ // Wait for the field list to render — useObject(view) inside ViewEditor resolves
146
+ // asynchronously after the outer story's type/view state is set, so the debug
147
+ // element can appear before the list items are in the DOM.
148
+ await waitFor(() => {
149
+ expect(screen.getByText('name')).toBeInTheDocument();
150
+ });
151
+
146
152
  // Find the delete button for the 'name' property.
147
153
  const nameProperty = screen.getByText('name');
148
154
  const propertyRow = nameProperty.closest('[role="listitem"]');
@@ -26,9 +26,9 @@ import {
26
26
  import { SchemaEx } from '@dxos/effect';
27
27
  import { invariant } from '@dxos/invariant';
28
28
  import { useObject, useQuery } from '@dxos/react-client/echo';
29
- import { IconButton, Input, Message, type ThemedClassName, useTranslation } from '@dxos/react-ui';
29
+ import { Input, Message, type ThemedClassName, ToggleIconButton, useTranslation } from '@dxos/react-ui';
30
30
  import { QueryForm, type QueryFormProps } from '@dxos/react-ui-components';
31
- import { List } from '@dxos/react-ui-list';
31
+ import { OrderedList } from '@dxos/react-ui-list';
32
32
  import {
33
33
  ParentLabelAnnotation,
34
34
  ProjectionModel,
@@ -36,19 +36,13 @@ import {
36
36
  createEchoChangeCallback,
37
37
  getTypeURIFromQuery,
38
38
  } from '@dxos/schema';
39
- import { mx, osTranslations } from '@dxos/ui-theme';
39
+ import { mx } from '@dxos/ui-theme';
40
40
 
41
41
  import { translationKey } from '#translations';
42
+ import { type FormFieldMap, type FormFieldRenderer, type FormFieldRendererProps } from '#types';
42
43
 
43
44
  import { FieldEditor } from '../FieldEditor';
44
- import {
45
- Form,
46
- type FormFieldComponent,
47
- type FormFieldComponentProps,
48
- FormFieldLabel,
49
- type FormFieldMap,
50
- type FormRootProps,
51
- } from '../Form';
45
+ import { CompactIconButton, Form, FormFieldHeader, FormFieldLabel, type FormRootProps } from '../Form';
52
46
 
53
47
  export type ViewEditorProps = ThemedClassName<
54
48
  {
@@ -64,7 +58,7 @@ export type ViewEditorProps = ThemedClassName<
64
58
  >;
65
59
 
66
60
  /**
67
- * Schema-based object form.
61
+ * View editor form.
68
62
  */
69
63
  export const ViewEditor = forwardRef<ProjectionModel | null, ViewEditorProps>(
70
64
  (
@@ -92,6 +86,7 @@ export const ViewEditor = forwardRef<ProjectionModel | null, ViewEditorProps>(
92
86
  if (!type) {
93
87
  return null;
94
88
  }
89
+
95
90
  const jsonSchema = type.jsonSchema;
96
91
 
97
92
  // Always use createEchoChangeCallback since the view is ECHO-backed.
@@ -117,6 +112,7 @@ export const ViewEditor = forwardRef<ProjectionModel | null, ViewEditorProps>(
117
112
  if (from._tag !== 'scope') {
118
113
  return undefined;
119
114
  }
115
+
120
116
  const feedScope = from.scopes.find((s) => s._tag === 'feed');
121
117
  return Option.fromNullable(feedScope).pipe(
122
118
  Option.map((s) => s.feedUri),
@@ -216,42 +212,54 @@ export const ViewEditor = forwardRef<ProjectionModel | null, ViewEditorProps>(
216
212
 
217
213
  return (
218
214
  <div className={mx(classNames)}>
219
- {/* If readonly is set, then the callout is not needed. */}
220
- {schemaReadonly && !readonly && (
221
- <Message.Root valence='info' classNames='my-form-padding'>
222
- <Message.Title>{t('system-schema.description')}</Message.Title>
223
- </Message.Root>
224
- )}
225
-
226
215
  {/* TODO(burdon): Is the form read-only or just the schema? */}
227
216
  <Form.Root schema={viewSchema} values={viewValues} fieldMap={fieldMap} db={db} onValuesChanged={handleUpdate}>
228
- <Form.FieldSet />
229
-
230
- {type && (
231
- <>
232
- <FormFieldLabel label={t('fields.label')} asChild />
233
- <FieldList
234
- type={type}
235
- view={view}
236
- registry={registry}
237
- readonly={readonly}
238
- showHeading={showHeading}
239
- onDelete={handleDelete}
240
- />
241
- </>
242
- )}
217
+ <Form.Viewport>
218
+ <Form.Content>
219
+ {/* If readonly is set, then the callout is not needed. */}
220
+ {schemaReadonly && !readonly && (
221
+ <Message.Root valence='info' classNames='my-form-padding'>
222
+ <Message.Title>{t('system-schema.description')}</Message.Title>
223
+ </Message.Root>
224
+ )}
225
+ <Form.FieldSet />
226
+ {type && (
227
+ <FieldList
228
+ type={type}
229
+ view={view}
230
+ registry={registry}
231
+ readonly={readonly}
232
+ showHeading={showHeading}
233
+ onDelete={handleDelete}
234
+ />
235
+ )}
236
+ </Form.Content>
237
+ </Form.Viewport>
243
238
  </Form.Root>
244
239
  </div>
245
240
  );
246
241
  },
247
242
  );
248
243
 
249
- type FieldListProps = Omit<
250
- Pick<ViewEditorProps, 'type' | 'view' | 'registry' | 'readonly' | 'showHeading' | 'onDelete'>,
251
- 'type'
252
- > & {
244
+ const customFields = ({ types, tags }: Pick<ViewEditorProps, 'types' | 'tags'>): Record<string, FormFieldRenderer> => ({
245
+ query: ({ type, readonly, label, getValue, onValueChange }: FormFieldRendererProps) => {
246
+ const handleChange = useCallback<NonNullable<QueryFormProps['onChange']>>(
247
+ (query) => onValueChange(type, query.ast),
248
+ [onValueChange],
249
+ );
250
+
251
+ return (
252
+ <Input.Root>
253
+ <FormFieldLabel readonly={readonly} label={label} />
254
+ <QueryForm initialQuery={getValue()} types={types} tags={tags} onChange={handleChange} />
255
+ </Input.Root>
256
+ );
257
+ },
258
+ });
259
+
260
+ type FieldListProps = {
253
261
  type: Type.AnyEntity;
254
- };
262
+ } & Pick<ViewEditorProps, 'view' | 'registry' | 'readonly' | 'showHeading' | 'onDelete'>;
255
263
 
256
264
  const FieldList = ({ type, view, registry, readonly, showHeading = false, onDelete }: FieldListProps) => {
257
265
  const atomRegistry = useContext(RegistryContext);
@@ -268,14 +276,12 @@ const FieldList = ({ type, view, registry, readonly, showHeading = false, onDele
268
276
  // Pass type only when mutable to allow schema mutations.
269
277
  const change = createEchoChangeCallback(view, Type.getDatabase(type) != null ? type : undefined);
270
278
 
271
- const model = new ProjectionModel({
279
+ return new ProjectionModel({
272
280
  registry: atomRegistry,
273
281
  view,
274
282
  baseSchema: jsonSchema,
275
283
  change,
276
284
  });
277
-
278
- return model;
279
285
  }, [atomRegistry, type, view]);
280
286
 
281
287
  const [expandedField, setExpandedField] = useState<View.FieldType['id']>();
@@ -286,13 +292,6 @@ const FieldList = ({ type, view, registry, readonly, showHeading = false, onDele
286
292
  setExpandedField(field.id);
287
293
  }, [projectionModel, readonly]);
288
294
 
289
- const handleToggleField = useCallback(
290
- (field: View.FieldType) => {
291
- setExpandedField((prevExpandedFieldId) => (prevExpandedFieldId === field.id ? undefined : field.id));
292
- },
293
- [readonly],
294
- );
295
-
296
295
  const handleDelete = useCallback(
297
296
  (fieldId: string) => {
298
297
  invariant(!readonly);
@@ -342,106 +341,77 @@ const FieldList = ({ type, view, registry, readonly, showHeading = false, onDele
342
341
  }
343
342
 
344
343
  return (
345
- <List.Root<View.FieldType>
344
+ <OrderedList.Root<View.FieldType>
346
345
  items={viewSnapshot.projection.fields as View.FieldType[]}
347
346
  isItem={Schema.is(View.FieldSchema)}
348
347
  getId={(field) => field.id}
349
348
  onMove={readonly ? undefined : handleMove}
350
349
  readonly={readonly}
350
+ expandedId={expandedField}
351
+ onExpandedChange={setExpandedField}
351
352
  >
352
353
  {({ items: fields }) => (
353
354
  <>
354
- {showHeading && <h3 className='text-sm'>{t('field-path.label')}</h3>}
355
- <div role='list' className='grid grid-cols-[min-content_1fr_min-content_min-content_min-content]'>
356
- {fields?.map((field) => {
355
+ <FormFieldHeader
356
+ label={t('fields.label')}
357
+ readonly={readonly}
358
+ add={{
359
+ label: t('add-property-button.label'),
360
+ disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
361
+ onClick: handleAdd,
362
+ }}
363
+ />
364
+ {showHeading && <FormFieldLabel standalone classNames='py-1' label={t('field-path.label')} />}
365
+ <OrderedList.Content>
366
+ {fields.map((field) => {
357
367
  const hidden = field.visible === false;
358
368
  return (
359
- <List.Item<View.FieldType>
369
+ <OrderedList.DetailItem<View.FieldType>
360
370
  key={field.id}
371
+ id={field.id}
361
372
  item={field}
362
- classNames={'grid grid-cols-subgrid col-span-5'}
363
- aria-expanded={expandedField === field.id}
364
- >
365
- <div className='grid grid-cols-subgrid col-span-5 rounded-xs cursor-pointer min-h-10 dx-hover'>
366
- <List.ItemDragHandle disabled={readonly || schemaReadonly} />
367
- <List.ItemTitle classNames={hidden && 'text-subdued'} onClick={() => handleToggleField(field)}>
368
- {field.path}
369
- </List.ItemTitle>
370
- <List.ItemIconButton
373
+ canDrag={!readonly && !schemaReadonly}
374
+ expandable={!readonly}
375
+ title={field.path}
376
+ titleClassNames={hidden ? 'text-subdued' : undefined}
377
+ actions={
378
+ <ToggleIconButton
379
+ iconOnly
380
+ variant='ghost'
381
+ active={hidden}
382
+ icon='ph--eye--regular'
383
+ activeIcon='ph--eye-closed--regular'
371
384
  label={t(hidden ? 'show-field.label' : 'hide-field.label')}
372
385
  data-testid={hidden ? 'show-field-button' : 'hide-field-button'}
373
- icon={hidden ? 'ph--eye-closed--regular' : 'ph--eye--regular'}
374
- autoHide={false}
375
386
  disabled={readonly || (!hidden && projectionModel.getFields().length <= 1)}
376
387
  onClick={() => (hidden ? handleShow(field.path) : handleHide(field.id))}
377
388
  />
378
- {!readonly && (
379
- <>
380
- <List.ItemDeleteButton
381
- label={t('delete-field.label')}
382
- autoHide={false}
383
- disabled={readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1}
384
- onClick={() => handleDelete(field.id)}
385
- data-testid='field.delete'
386
- />
387
- <List.ItemIconButton
388
- iconOnly
389
- variant='ghost'
390
- label={t('toggle-expand.label', { ns: osTranslations })}
391
- icon={expandedField === field.id ? 'ph--caret-down--regular' : 'ph--caret-right--regular'}
392
- onClick={() => handleToggleField(field)}
393
- data-testid='field.toggle'
394
- />
395
- </>
396
- )}
397
- </div>
398
- {expandedField === field.id && !readonly && (
399
- <div className='col-span-full mt-1 mb-1 border border-separator rounded-md'>
400
- <FieldEditor
401
- readonly={readonly || schemaReadonly}
402
- registry={registry}
403
- projection={projectionModel}
404
- field={field}
405
- onSave={handleClose}
389
+ }
390
+ trailing={
391
+ !readonly && (
392
+ <CompactIconButton
393
+ icon='ph--x--regular'
394
+ label={t('delete-field.label')}
395
+ disabled={schemaReadonly || viewSnapshot.projection.fields.length <= 1}
396
+ onClick={() => handleDelete(field.id)}
397
+ data-testid='field.delete'
406
398
  />
407
- </div>
408
- )}
409
- </List.Item>
399
+ )
400
+ }
401
+ >
402
+ <FieldEditor
403
+ readonly={readonly || schemaReadonly}
404
+ registry={registry}
405
+ projection={projectionModel}
406
+ field={field}
407
+ onSave={handleClose}
408
+ />
409
+ </OrderedList.DetailItem>
410
410
  );
411
411
  })}
412
- </div>
413
- {!readonly && !expandedField && (
414
- <div className='my-form-padding'>
415
- <IconButton
416
- icon='ph--plus--regular'
417
- label={t('add-property-button.label')}
418
- onClick={handleAdd}
419
- disabled={viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT}
420
- classNames='w-full'
421
- />
422
- </div>
423
- )}
412
+ </OrderedList.Content>
424
413
  </>
425
414
  )}
426
- </List.Root>
415
+ </OrderedList.Root>
427
416
  );
428
417
  };
429
-
430
- const customFields = ({
431
- types,
432
- tags,
433
- }: Pick<ViewEditorProps, 'types' | 'tags'>): Record<string, FormFieldComponent> => ({
434
- query: ({ type, readonly, label, getValue, onValueChange }: FormFieldComponentProps) => {
435
- const handleChange = useCallback<NonNullable<QueryFormProps['onChange']>>(
436
- (query) => onValueChange(type, query.ast),
437
- [onValueChange],
438
- );
439
-
440
- return (
441
- <Input.Root>
442
- <FormFieldLabel readonly={readonly} label={label} />
443
- <QueryForm initialQuery={getValue()} types={types} tags={tags} onChange={handleChange} />
444
- </Input.Root>
445
- );
446
- },
447
- });
@@ -9,5 +9,4 @@ export * from './ObjectPicker';
9
9
  export * from './ObjectProperties';
10
10
  export * from './ObjectTree';
11
11
  export * from './RefEditor';
12
- export * from './Settings';
13
12
  export * from './ViewEditor';
@@ -2,5 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export * from './useAsyncFieldEffect';
6
+ export * from './useFormContext';
5
7
  export * from './useFormHandler';
6
8
  export * from './useKeyHandler';