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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +0 -1
  3. package/dist/lib/browser/index.mjs +4054 -2217
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/translations.mjs +87 -0
  7. package/dist/lib/browser/translations.mjs.map +7 -0
  8. package/dist/lib/node-esm/index.mjs +4054 -2217
  9. package/dist/lib/node-esm/index.mjs.map +4 -4
  10. package/dist/lib/node-esm/meta.json +1 -1
  11. package/dist/lib/node-esm/translations.mjs +89 -0
  12. package/dist/lib/node-esm/translations.mjs.map +7 -0
  13. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +8 -8
  14. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  15. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +89 -5
  16. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/Form.d.ts +135 -25
  18. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/Form.stories.d.ts +207 -56
  20. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/FormField.d.ts +52 -0
  22. package/dist/types/src/components/Form/FormField.d.ts.map +1 -0
  23. package/dist/types/src/components/Form/FormFieldComponent.d.ts +98 -0
  24. package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -0
  25. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts +9 -0
  26. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -0
  27. package/dist/types/src/components/Form/FormFieldSet.d.ts +26 -0
  28. package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -0
  29. package/dist/types/src/components/Form/FormTooltipsContext.d.ts +19 -0
  30. package/dist/types/src/components/Form/FormTooltipsContext.d.ts.map +1 -0
  31. package/dist/types/src/components/Form/Layout/FormLayout.d.ts +50 -0
  32. package/dist/types/src/components/Form/Layout/FormLayout.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts +123 -0
  34. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts +2 -0
  36. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts.map +1 -0
  37. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts +2 -0
  38. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts.map +1 -0
  39. package/dist/types/src/components/Form/Layout/annotation.d.ts +30 -0
  40. package/dist/types/src/components/Form/Layout/annotation.d.ts.map +1 -0
  41. package/dist/types/src/components/Form/Layout/index.d.ts +4 -0
  42. package/dist/types/src/components/Form/Layout/index.d.ts.map +1 -0
  43. package/dist/types/src/components/Form/Layout/parser.d.ts +31 -0
  44. package/dist/types/src/components/Form/Layout/parser.d.ts.map +1 -0
  45. package/dist/types/src/components/Form/Layout/parser.test.d.ts +2 -0
  46. package/dist/types/src/components/Form/Layout/parser.test.d.ts.map +1 -0
  47. package/dist/types/src/components/Form/fields/ArrayField.d.ts +18 -0
  48. package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -0
  49. package/dist/types/src/components/Form/fields/BooleanField.d.ts +4 -0
  50. package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -0
  51. package/dist/types/src/components/Form/fields/DateField.d.ts +4 -0
  52. package/dist/types/src/components/Form/fields/DateField.d.ts.map +1 -0
  53. package/dist/types/src/components/Form/fields/GeoPointField.d.ts +5 -0
  54. package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -0
  55. package/dist/types/src/components/Form/fields/InlineRefField.d.ts +13 -0
  56. package/dist/types/src/components/Form/fields/InlineRefField.d.ts.map +1 -0
  57. package/dist/types/src/components/Form/fields/MarkdownField.d.ts +11 -0
  58. package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -0
  59. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +89 -0
  60. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
  61. package/dist/types/src/components/Form/fields/NumberField.d.ts +4 -0
  62. package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -0
  63. package/dist/types/src/components/Form/fields/RefField.d.ts +34 -0
  64. package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -0
  65. package/dist/types/src/components/Form/fields/RefField.test.d.ts +2 -0
  66. package/dist/types/src/components/Form/fields/RefField.test.d.ts.map +1 -0
  67. package/dist/types/src/components/Form/fields/SelectField.d.ts +13 -0
  68. package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -0
  69. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +5 -0
  70. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -0
  71. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +89 -0
  72. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -0
  73. package/dist/types/src/components/Form/fields/TextAreaField.d.ts +4 -0
  74. package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -0
  75. package/dist/types/src/components/Form/fields/TextField.d.ts +4 -0
  76. package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -0
  77. package/dist/types/src/components/Form/fields/TupleField.d.ts +6 -0
  78. package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -0
  79. package/dist/types/src/components/Form/fields/index.d.ts +14 -0
  80. package/dist/types/src/components/Form/fields/index.d.ts.map +1 -0
  81. package/dist/types/src/components/Form/index.d.ts +5 -4
  82. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  83. package/dist/types/src/components/Form/meta-tags.d.ts +30 -0
  84. package/dist/types/src/components/Form/meta-tags.d.ts.map +1 -0
  85. package/dist/types/src/components/Form/meta-tags.test.d.ts +2 -0
  86. package/dist/types/src/components/Form/meta-tags.test.d.ts.map +1 -0
  87. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +8 -0
  88. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
  89. package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts +87 -0
  90. package/dist/types/src/components/ObjectForm/ObjectForm.stories.d.ts.map +1 -0
  91. package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
  92. package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
  93. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +68 -0
  94. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
  95. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +92 -0
  96. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
  97. package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
  98. package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
  99. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
  100. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
  101. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +132 -0
  102. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
  103. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
  104. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
  105. package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
  106. package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
  107. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts +9 -0
  108. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts.map +1 -0
  109. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts +91 -0
  110. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/ObjectTree/index.d.ts +2 -0
  112. package/dist/types/src/components/ObjectTree/index.d.ts.map +1 -0
  113. package/dist/types/src/components/RefEditor/RefEditor.d.ts +73 -0
  114. package/dist/types/src/components/RefEditor/RefEditor.d.ts.map +1 -0
  115. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts +92 -0
  116. package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts.map +1 -0
  117. package/dist/types/src/components/RefEditor/index.d.ts +3 -0
  118. package/dist/types/src/components/RefEditor/index.d.ts.map +1 -0
  119. package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts +47 -0
  120. package/dist/types/src/components/RefEditor/ref-editor-extension.d.ts.map +1 -0
  121. package/dist/types/src/components/Settings/Settings.d.ts +51 -0
  122. package/dist/types/src/components/Settings/Settings.d.ts.map +1 -0
  123. package/dist/types/src/components/Settings/Settings.stories.d.ts +89 -0
  124. package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -0
  125. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
  126. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
  127. package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
  128. package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
  129. package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
  130. package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
  131. package/dist/types/src/components/Settings/index.d.ts +4 -0
  132. package/dist/types/src/components/Settings/index.d.ts.map +1 -0
  133. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +21 -11
  134. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  135. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +91 -9
  136. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  137. package/dist/types/src/components/index.d.ts +6 -2
  138. package/dist/types/src/components/index.d.ts.map +1 -1
  139. package/dist/types/src/components/testing.d.ts +14 -4
  140. package/dist/types/src/components/testing.d.ts.map +1 -1
  141. package/dist/types/src/hooks/index.d.ts +2 -3
  142. package/dist/types/src/hooks/index.d.ts.map +1 -1
  143. package/dist/types/src/hooks/useFormHandler.d.ts +82 -0
  144. package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -0
  145. package/dist/types/src/hooks/useKeyHandler.d.ts +7 -0
  146. package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -0
  147. package/dist/types/src/index.d.ts +0 -2
  148. package/dist/types/src/index.d.ts.map +1 -1
  149. package/dist/types/src/translations.d.ts +70 -55
  150. package/dist/types/src/translations.d.ts.map +1 -1
  151. package/dist/types/src/util/field-type.d.ts +19 -0
  152. package/dist/types/src/util/field-type.d.ts.map +1 -0
  153. package/dist/types/src/util/field.d.ts +3 -3
  154. package/dist/types/src/util/field.d.ts.map +1 -1
  155. package/dist/types/src/util/formatting.d.ts +2 -2
  156. package/dist/types/src/util/formatting.d.ts.map +1 -1
  157. package/dist/types/src/util/index.d.ts +2 -1
  158. package/dist/types/src/util/index.d.ts.map +1 -1
  159. package/dist/types/src/util/properties.d.ts +35 -0
  160. package/dist/types/src/util/properties.d.ts.map +1 -0
  161. package/dist/types/src/util/properties.test.d.ts +2 -0
  162. package/dist/types/src/util/properties.test.d.ts.map +1 -0
  163. package/dist/types/src/util/refs.d.ts +3 -3
  164. package/dist/types/src/util/refs.d.ts.map +1 -1
  165. package/dist/types/tsconfig.tsbuildinfo +1 -1
  166. package/package.json +64 -47
  167. package/src/components/FieldEditor/FieldEditor.stories.tsx +49 -31
  168. package/src/components/FieldEditor/FieldEditor.test.tsx +4 -2
  169. package/src/components/FieldEditor/FieldEditor.tsx +100 -97
  170. package/src/components/Form/AUDIT.md +17 -0
  171. package/src/components/Form/Form.stories.tsx +151 -221
  172. package/src/components/Form/Form.tsx +461 -95
  173. package/src/components/Form/FormField.tsx +345 -0
  174. package/src/components/Form/FormFieldComponent.stories.tsx +65 -0
  175. package/src/components/Form/FormFieldComponent.tsx +253 -0
  176. package/src/components/Form/FormFieldSet.tsx +213 -0
  177. package/src/components/Form/FormTooltipsContext.ts +25 -0
  178. package/src/components/Form/Layout/FormLayout.stories.test.tsx +51 -0
  179. package/src/components/Form/Layout/FormLayout.stories.tsx +422 -0
  180. package/src/components/Form/Layout/FormLayout.test.ts +59 -0
  181. package/src/components/Form/Layout/FormLayout.tsx +251 -0
  182. package/src/components/Form/Layout/annotation.ts +38 -0
  183. package/src/components/Form/Layout/index.ts +7 -0
  184. package/src/components/Form/Layout/parser.test.ts +120 -0
  185. package/src/components/Form/Layout/parser.ts +167 -0
  186. package/src/components/Form/README.md +3 -0
  187. package/src/components/Form/fields/ArrayField.tsx +173 -0
  188. package/src/components/Form/fields/BooleanField.tsx +22 -0
  189. package/src/components/Form/fields/DateField.tsx +101 -0
  190. package/src/components/Form/fields/GeoPointField.tsx +124 -0
  191. package/src/components/Form/fields/InlineRefField.tsx +138 -0
  192. package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
  193. package/src/components/Form/fields/MarkdownField.tsx +167 -0
  194. package/src/components/Form/fields/NumberField.tsx +76 -0
  195. package/src/components/Form/fields/RefField.test.ts +45 -0
  196. package/src/components/Form/fields/RefField.tsx +266 -0
  197. package/src/components/Form/fields/SelectField.tsx +77 -0
  198. package/src/components/Form/fields/SelectOptionField.stories.tsx +66 -0
  199. package/src/components/Form/{custom/SelectOptionsInput.tsx → fields/SelectOptionField.tsx} +39 -32
  200. package/src/components/Form/fields/TextAreaField.tsx +38 -0
  201. package/src/components/Form/fields/TextField.tsx +38 -0
  202. package/src/components/Form/fields/TupleField.tsx +55 -0
  203. package/src/components/Form/fields/index.ts +17 -0
  204. package/src/components/Form/index.ts +6 -4
  205. package/src/components/Form/meta-tags.test.ts +47 -0
  206. package/src/components/Form/meta-tags.ts +33 -0
  207. package/src/components/ObjectForm/ObjectForm.stories.tsx +62 -0
  208. package/src/components/ObjectForm/ObjectForm.tsx +111 -0
  209. package/src/components/{ControlSection → ObjectForm}/index.ts +1 -1
  210. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +212 -0
  211. package/src/components/ObjectPicker/ObjectPicker.tsx +202 -0
  212. package/src/components/ObjectPicker/index.ts +5 -0
  213. package/src/components/ObjectProperties/ObjectProperties.stories.tsx +350 -0
  214. package/src/components/ObjectProperties/ObjectProperties.test.tsx +111 -0
  215. package/src/components/ObjectProperties/ObjectProperties.tsx +146 -0
  216. package/src/components/ObjectProperties/index.ts +5 -0
  217. package/src/components/ObjectTree/ObjectTree.stories.tsx +134 -0
  218. package/src/components/ObjectTree/ObjectTree.tsx +190 -0
  219. package/src/components/ObjectTree/index.ts +5 -0
  220. package/src/components/RefEditor/RefEditor.stories.tsx +148 -0
  221. package/src/components/RefEditor/RefEditor.tsx +275 -0
  222. package/src/components/RefEditor/index.ts +6 -0
  223. package/src/components/RefEditor/ref-editor-extension.ts +254 -0
  224. package/src/components/Settings/AUDIT.md +51 -0
  225. package/src/components/Settings/Settings.stories.tsx +104 -0
  226. package/src/components/Settings/Settings.tsx +81 -0
  227. package/src/components/Settings/SettingsFieldSet.tsx +257 -0
  228. package/src/components/Settings/SettingsItem.tsx +58 -0
  229. package/src/components/Settings/SettingsSelectField.tsx +59 -0
  230. package/src/components/Settings/index.ts +7 -0
  231. package/src/components/ViewEditor/ViewEditor.stories.tsx +132 -64
  232. package/src/components/ViewEditor/ViewEditor.test.tsx +23 -22
  233. package/src/components/ViewEditor/ViewEditor.tsx +378 -216
  234. package/src/components/index.ts +6 -3
  235. package/src/components/testing.tsx +31 -12
  236. package/src/hooks/index.ts +2 -3
  237. package/src/hooks/useFormHandler.ts +380 -0
  238. package/src/hooks/useKeyHandler.tsx +37 -0
  239. package/src/index.ts +0 -4
  240. package/src/translations.ts +76 -59
  241. package/src/util/field-type.ts +60 -0
  242. package/src/util/field.ts +33 -43
  243. package/src/util/formatting.ts +22 -22
  244. package/src/util/index.ts +2 -1
  245. package/src/util/properties.test.ts +153 -0
  246. package/src/util/properties.ts +100 -0
  247. package/src/util/refs.ts +20 -19
  248. package/src/vite-env.d.ts +10 -0
  249. package/dist/types/src/components/ControlSection/ControlSection.d.ts +0 -23
  250. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +0 -1
  251. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +0 -8
  252. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +0 -1
  253. package/dist/types/src/components/ControlSection/index.d.ts +0 -2
  254. package/dist/types/src/components/ControlSection/index.d.ts.map +0 -1
  255. package/dist/types/src/components/Form/ArrayField.d.ts +0 -16
  256. package/dist/types/src/components/Form/ArrayField.d.ts.map +0 -1
  257. package/dist/types/src/components/Form/Defaults.d.ts +0 -14
  258. package/dist/types/src/components/Form/Defaults.d.ts.map +0 -1
  259. package/dist/types/src/components/Form/FormActions.d.ts +0 -9
  260. package/dist/types/src/components/Form/FormActions.d.ts.map +0 -1
  261. package/dist/types/src/components/Form/FormContent.d.ts +0 -57
  262. package/dist/types/src/components/Form/FormContent.d.ts.map +0 -1
  263. package/dist/types/src/components/Form/FormContext.d.ts +0 -23
  264. package/dist/types/src/components/Form/FormContext.d.ts.map +0 -1
  265. package/dist/types/src/components/Form/Input.d.ts +0 -26
  266. package/dist/types/src/components/Form/Input.d.ts.map +0 -1
  267. package/dist/types/src/components/Form/RefField.d.ts +0 -12
  268. package/dist/types/src/components/Form/RefField.d.ts.map +0 -1
  269. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +0 -4
  270. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +0 -1
  271. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +0 -4
  272. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +0 -1
  273. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +0 -7
  274. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +0 -1
  275. package/dist/types/src/components/Form/custom/TupleInput.d.ts +0 -6
  276. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +0 -1
  277. package/dist/types/src/components/Form/custom/index.d.ts +0 -4
  278. package/dist/types/src/components/Form/custom/index.d.ts.map +0 -1
  279. package/dist/types/src/components/Form/factory.d.ts +0 -8
  280. package/dist/types/src/components/Form/factory.d.ts.map +0 -1
  281. package/dist/types/src/components/deprecated/Form.d.ts +0 -15
  282. package/dist/types/src/components/deprecated/Form.d.ts.map +0 -1
  283. package/dist/types/src/components/deprecated/Form.stories.d.ts +0 -13
  284. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +0 -1
  285. package/dist/types/src/components/deprecated/FormInput.d.ts +0 -16
  286. package/dist/types/src/components/deprecated/FormInput.d.ts.map +0 -1
  287. package/dist/types/src/components/deprecated/index.d.ts +0 -2
  288. package/dist/types/src/components/deprecated/index.d.ts.map +0 -1
  289. package/dist/types/src/hooks/useForm.d.ts +0 -67
  290. package/dist/types/src/hooks/useForm.d.ts.map +0 -1
  291. package/dist/types/src/hooks/useQueryRefOptions.d.ts +0 -23
  292. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +0 -1
  293. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +0 -8
  294. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +0 -1
  295. package/dist/types/src/util/schema.d.ts +0 -3
  296. package/dist/types/src/util/schema.d.ts.map +0 -1
  297. package/src/components/ControlSection/ControlSection.stories.tsx +0 -42
  298. package/src/components/ControlSection/ControlSection.tsx +0 -139
  299. package/src/components/Form/ArrayField.tsx +0 -125
  300. package/src/components/Form/Defaults.tsx +0 -204
  301. package/src/components/Form/FormActions.tsx +0 -54
  302. package/src/components/Form/FormContent.tsx +0 -241
  303. package/src/components/Form/FormContext.tsx +0 -110
  304. package/src/components/Form/Input.tsx +0 -51
  305. package/src/components/Form/RefField.tsx +0 -214
  306. package/src/components/Form/custom/GeoPointInput.tsx +0 -72
  307. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +0 -62
  308. package/src/components/Form/custom/TupleInput.tsx +0 -47
  309. package/src/components/Form/custom/index.ts +0 -7
  310. package/src/components/Form/factory.tsx +0 -31
  311. package/src/components/deprecated/Form.stories.tsx +0 -63
  312. package/src/components/deprecated/Form.tsx +0 -119
  313. package/src/components/deprecated/FormInput.tsx +0 -71
  314. package/src/components/deprecated/index.ts +0 -5
  315. package/src/hooks/useForm.ts +0 -293
  316. package/src/hooks/useQueryRefOptions.ts +0 -53
  317. package/src/hooks/useRefQueryLookupHandler.ts +0 -39
  318. package/src/util/schema.ts +0 -14
@@ -0,0 +1,266 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useMemo, useState } from 'react';
6
+
7
+ import '@dxos/lit-ui/dx-tag-picker.pcss';
8
+ import { type Database, Entity, Filter, Obj, Query, Ref, Scope, Type } from '@dxos/echo';
9
+ import { useQuery, useType as defaultUseType } from '@dxos/echo-react';
10
+ import { ANY_OBJECT_TYPENAME, ReferenceAnnotationId, type ReferenceAnnotationValue } from '@dxos/echo/internal';
11
+ import { SchemaEx } from '@dxos/effect';
12
+ import { DXN, EID, URI } from '@dxos/keys';
13
+ import { DxAnchor } from '@dxos/lit-ui/react';
14
+ import { Button, Icon, Input, useTranslation } from '@dxos/react-ui';
15
+ import { ParentLabelAnnotationId } from '@dxos/schema';
16
+
17
+ import { translationKey } from '#translations';
18
+
19
+ import { ObjectPicker, type ObjectPickerContentProps, type RefOption } from '../../ObjectPicker';
20
+ import { omitHiddenFormFields, omitId } from '../Form';
21
+ import { type FormFieldComponentProps, FormFieldLabel } from '../FormFieldComponent';
22
+
23
+ // TODO(burdon): Factor out.
24
+ const isRefSnapshot = (val: any): val is { '/': string } => {
25
+ return typeof val === 'object' && typeof (val as any)?.['/'] === 'string';
26
+ };
27
+
28
+ /**
29
+ * Find the option a ref-like form value points at. Matches on the local (entity-id) form so a bare local EID
30
+ * (`echo:/<id>`, produced by `Ref.make`) still resolves against an option keyed by the entity's qualified
31
+ * self URI (`echo://<space>/<id>`). Returns `undefined` when the value is not a ref or no option matches.
32
+ *
33
+ * Comparing by entity id is only sound within one space (ids are unique there, not globally). Two EIDs that
34
+ * both carry a space authority must therefore agree on it: a qualified value and a qualified option from
35
+ * different spaces never match, even when their entity ids coincide.
36
+ */
37
+ export const findRefOption = (value: unknown, options: RefOption[]): RefOption | undefined => {
38
+ const isRef = Ref.isRef(value);
39
+ if (!isRef && !isRefSnapshot(value)) {
40
+ return undefined;
41
+ }
42
+ const valueEid = EID.tryParse(isRef ? value.uri : value['/']);
43
+ if (!valueEid) {
44
+ return undefined;
45
+ }
46
+ const valueSpaceId = EID.getSpaceId(valueEid);
47
+ const valueLocal = EID.toLocal(valueEid);
48
+ return options.find((option) => {
49
+ const optionEid = EID.tryParse(option.id);
50
+ if (!optionEid) {
51
+ return false;
52
+ }
53
+ const optionSpaceId = EID.getSpaceId(optionEid);
54
+ if (valueSpaceId != null && optionSpaceId != null && valueSpaceId !== optionSpaceId) {
55
+ return false;
56
+ }
57
+ return EID.equals(EID.toLocal(optionEid), valueLocal);
58
+ });
59
+ };
60
+
61
+ const defaultGetOptions: NonNullable<RefFieldProps['getOptions']> = (
62
+ results,
63
+ { parentLabel, getTypePlaceholder } = {},
64
+ ) =>
65
+ results
66
+ // When labeling by parent, only surface objects that actually have a parent — an unparented object
67
+ // (e.g. a system feed) has no meaningful parent to label by.
68
+ .filter((result) => !parentLabel || Obj.getParent(result as Obj.Unknown) != null)
69
+ .map((result) => {
70
+ const id = Entity.getURI(result, { prefer: 'named' });
71
+ const parent = parentLabel ? Obj.getParent(result as Obj.Unknown) : undefined;
72
+ const labelEntity = parent ?? result;
73
+ const typename = Entity.getTypename(labelEntity);
74
+ // Fall back to the entity's type placeholder when it has no label of its own — matching the
75
+ // app-graph/navtree (`object-name.placeholder` in the entity's typename namespace).
76
+ const label = Entity.getLabel(labelEntity) ?? (typename ? getTypePlaceholder?.(typename) : undefined) ?? id;
77
+ return { id, label };
78
+ });
79
+
80
+ const defaultUseResults: NonNullable<RefFieldProps['useResults']> = (db, typename) =>
81
+ useQuery(
82
+ db,
83
+ !typename
84
+ ? Query.select(Filter.nothing())
85
+ : typename === ANY_OBJECT_TYPENAME
86
+ ? // Untyped refs show space objects only; the registry is too broad for "any".
87
+ Query.select(Filter.everything())
88
+ : // Include registry scope so keyed entities (blueprints, operations) appear as options.
89
+ Query.select(Filter.type(DXN.make(typename))).from(Scope.space(), Scope.registry()),
90
+ );
91
+
92
+ export type RefFieldProps = FormFieldComponentProps &
93
+ Pick<
94
+ ObjectPickerContentProps,
95
+ 'createOptionLabel' | 'createOptionIcon' | 'createInitialValuePath' | 'createFieldMap'
96
+ > & {
97
+ db?: Database.Database;
98
+ // TODO(burdon): Replace hooks with callbacks.
99
+ useType?: (db?: Database.Database, typeUri?: URI.URI) => Type.AnyEntity;
100
+ useResults?: (db?: Database.Database, typename?: string) => Entity.Any[];
101
+ getOptions?: (
102
+ objects: Entity.Any[],
103
+ options?: { parentLabel?: boolean; getTypePlaceholder?: (typename: string) => string },
104
+ ) => RefOption[];
105
+ /**
106
+ * Persist a newly-created object. Called after the user fills out the
107
+ * inline create form and clicks Save. Should add the object to the
108
+ * database and return it (sync or async). The returned object is then
109
+ * wired into this slot's form value as a Ref.
110
+ */
111
+ onCreate?: (schema: Type.AnyEntity, values: any) => Obj.Unknown | Promise<Obj.Unknown> | undefined | void;
112
+ };
113
+
114
+ export const RefField = (props: RefFieldProps) => {
115
+ const {
116
+ type,
117
+ readonly,
118
+ label,
119
+ jsonPath,
120
+ placeholder,
121
+ layout,
122
+ getStatus,
123
+ getValue,
124
+ createOptionLabel,
125
+ createOptionIcon,
126
+ createInitialValuePath,
127
+ createFieldMap,
128
+ db,
129
+ useType = defaultUseType,
130
+ useResults = defaultUseResults,
131
+ getOptions = defaultGetOptions,
132
+ onCreate,
133
+ onValueChange,
134
+ } = props;
135
+ const { t } = useTranslation(translationKey);
136
+ const { status, error } = getStatus();
137
+
138
+ const typename = useMemo(
139
+ () => (type ? SchemaEx.findAnnotation<ReferenceAnnotationValue>(type, ReferenceAnnotationId)?.typename : undefined),
140
+ [type],
141
+ );
142
+
143
+ // Resolve a type-based placeholder label for entities that have no label of their own — the entity's
144
+ // `object-name.placeholder` in its own typename namespace, like the app-graph/navtree. Falls back to a
145
+ // humanized typename segment so we never surface a raw DXN for a type that hasn't registered one.
146
+ const getTypePlaceholder = useCallback(
147
+ (placeholderTypename: string): string => {
148
+ const segment = placeholderTypename.split(/[.:/]/).filter(Boolean).pop() ?? placeholderTypename;
149
+ const humanized = segment.charAt(0).toUpperCase() + segment.slice(1);
150
+ return t('object-name.placeholder', { ns: placeholderTypename, defaultValue: humanized });
151
+ },
152
+ [t],
153
+ );
154
+
155
+ const results = useResults(db, typename);
156
+ const options = useMemo(() => {
157
+ const parentLabel = type ? SchemaEx.findAnnotation<boolean>(type, ParentLabelAnnotationId) === true : false;
158
+ return getOptions(results, { parentLabel, getTypePlaceholder });
159
+ }, [results, getOptions, type, getTypePlaceholder]);
160
+
161
+ const handleGetValue = useCallback(() => findRefOption(getValue(), options), [options, getValue]);
162
+
163
+ const item = handleGetValue();
164
+ const selectedIds = useMemo(() => (item ? [item.id] : []), [item]);
165
+ const createSchema = useType(db, typename && typename !== ANY_OBJECT_TYPENAME ? DXN.make(typename) : undefined);
166
+
167
+ // Lift the popover open state so we can dismiss it after a successful create.
168
+ const [open, setOpen] = useState(false);
169
+
170
+ const handleCreate = useCallback(
171
+ async (values: any) => {
172
+ if (!createSchema || !onCreate) {
173
+ return;
174
+ }
175
+ const newObject = await onCreate(createSchema, values);
176
+ if (newObject) {
177
+ // Wire the newly-created object into this slot's form value. ArrayField
178
+ // owns the array; this RefField represents a single slot, so writing a
179
+ // Ref via `onValueChange` populates that slot.
180
+ onValueChange(type, Ref.make(newObject));
181
+ }
182
+ setOpen(false);
183
+ },
184
+ [createSchema, onCreate, type, onValueChange],
185
+ );
186
+
187
+ const handleUpdate = useCallback(
188
+ (id: string | undefined) => {
189
+ const item = options.find((option) => option.id === id);
190
+ const ref = item ? Ref.fromURI(URI.make(item.id)) : undefined;
191
+ onValueChange(type, ref);
192
+ },
193
+ [options, type, onValueChange],
194
+ );
195
+
196
+ const handleSelect = useCallback(
197
+ (id: string) => {
198
+ if (item?.id === id) {
199
+ handleUpdate(undefined);
200
+ } else {
201
+ handleUpdate(id);
202
+ }
203
+ },
204
+ [item, handleUpdate],
205
+ );
206
+
207
+ if (!typename || ((readonly || layout === 'static') && !item)) {
208
+ return null;
209
+ }
210
+
211
+ return (
212
+ <Input.Root validationValence={status}>
213
+ {layout !== 'inline' && <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />}
214
+ <div>
215
+ {readonly ? (
216
+ !item ? (
217
+ <p className='text-description mb-2'>{t('empty-readonly-ref-field.label')}</p>
218
+ ) : (
219
+ <DxAnchor key={item.id} dxn={item.id} rootclassname='me-1'>
220
+ {item.label}
221
+ </DxAnchor>
222
+ )
223
+ ) : (
224
+ <ObjectPicker.Root open={open} onOpenChange={setOpen}>
225
+ <ObjectPicker.Trigger asChild classNames='p-0'>
226
+ {item ? (
227
+ <div className='flex gap-form-gap w-full'>
228
+ <Input.Root key={item.id}>
229
+ <Input.TextInput value={item.label} readOnly classNames='w-full' />
230
+ </Input.Root>
231
+ </div>
232
+ ) : (
233
+ <Button classNames='w-full text-start gap-form-gap'>
234
+ <div className='grow overflow-hidden'>
235
+ <span className='truncate text-description'>
236
+ {placeholder || label || t('ref-field.placeholder')}
237
+ </span>
238
+ </div>
239
+ <Icon size={3} icon='ph--caret-down--bold' />
240
+ </Button>
241
+ )}
242
+ </ObjectPicker.Trigger>
243
+ <ObjectPicker.Portal>
244
+ <ObjectPicker.Content
245
+ classNames='dx-card-popover-width'
246
+ options={options}
247
+ selectedIds={selectedIds}
248
+ // Strip hidden (`FormInputAnnotation.set(false)`) fields so the
249
+ // form's validator doesn't reject required-but-hidden fields
250
+ // such as backing-object refs supplied by a `FactoryAnnotation`.
251
+ createSchema={createSchema && omitHiddenFormFields(omitId(Type.getSchema(createSchema)))}
252
+ createOptionLabel={createOptionLabel}
253
+ createOptionIcon={createOptionIcon}
254
+ createInitialValuePath={createInitialValuePath}
255
+ createFieldMap={createFieldMap}
256
+ onCreate={handleCreate}
257
+ onSelect={handleSelect}
258
+ />
259
+ </ObjectPicker.Portal>
260
+ </ObjectPicker.Root>
261
+ )}
262
+ </div>
263
+ {layout === 'full' && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
264
+ </Input.Root>
265
+ );
266
+ };
@@ -0,0 +1,77 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { Icon, Input, Select, type SelectRootProps } from '@dxos/react-ui';
8
+ import { getStyles } from '@dxos/ui-theme';
9
+
10
+ import { type FormFieldComponentProps, FormFieldLabel } from '../FormFieldComponent';
11
+
12
+ export type SelectFieldOptions = FormFieldComponentProps & {
13
+ options?: Array<{ value: string | number; label?: string; secondaryLabel?: string; icon?: string; iconHue?: string }>;
14
+ };
15
+
16
+ export const SelectField = ({
17
+ type,
18
+ readonly,
19
+ label,
20
+ jsonPath,
21
+ layout,
22
+ placeholder,
23
+ options,
24
+ getStatus,
25
+ getValue,
26
+ onValueChange,
27
+ }: SelectFieldOptions) => {
28
+ const { status, error } = getStatus();
29
+ const value = getValue() as string | undefined;
30
+
31
+ const handleValueChange = useCallback<NonNullable<SelectRootProps['onValueChange']>>(
32
+ (value) => onValueChange(type, value),
33
+ [type, onValueChange],
34
+ );
35
+
36
+ if ((readonly || layout === 'static') && value == null) {
37
+ return null;
38
+ }
39
+
40
+ return (
41
+ <Input.Root validationValence={status}>
42
+ {layout !== 'inline' && <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />}
43
+ {layout === 'static' ? (
44
+ <p>{options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)}</p>
45
+ ) : (
46
+ <Select.Root value={value} onValueChange={handleValueChange}>
47
+ {/* TODO(burdon): Placeholder not working? */}
48
+ <Select.TriggerButton classNames='w-full' disabled={!!readonly} placeholder={placeholder} />
49
+ <Select.Portal>
50
+ <Select.Content>
51
+ <Select.Viewport>
52
+ {options?.map(({ value, label, secondaryLabel, icon, iconHue }) => (
53
+ // NOTE: Numeric values are converted to and from strings.
54
+ <Select.Option key={String(value)} value={String(value)}>
55
+ <span className='flex items-center flex-row gap-2'>
56
+ {icon && <Icon icon={icon} classNames={getIconHueStyles(iconHue)} />}
57
+ {label ?? String(value)}
58
+ {secondaryLabel && <span className='text-subdued text-xs'>{secondaryLabel}</span>}
59
+ </span>
60
+ </Select.Option>
61
+ ))}
62
+ </Select.Viewport>
63
+ <Select.Arrow />
64
+ </Select.Content>
65
+ </Select.Portal>
66
+ </Select.Root>
67
+ )}
68
+ {layout === 'full' && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
69
+ </Input.Root>
70
+ );
71
+ };
72
+
73
+ const getIconHueStyles = (iconHue?: string): string | undefined => {
74
+ const styles = iconHue ? getStyles(iconHue) : undefined;
75
+
76
+ return styles?.fg;
77
+ };
@@ -0,0 +1,66 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Schema from 'effect/Schema';
7
+ import React, { useState } from 'react';
8
+
9
+ import { SelectOption } from '@dxos/echo/Format';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+
12
+ import { translations } from '#translations';
13
+
14
+ import { TestLayout } from '../../testing';
15
+ import { Form } from '../Form';
16
+ import { SelectOptionField } from './SelectOptionField';
17
+
18
+ const schema = Schema.Struct({
19
+ options: Schema.Array(SelectOption).pipe(Schema.mutable),
20
+ }).pipe(Schema.mutable);
21
+
22
+ const DefaultStory = () => {
23
+ const [values, setValues] = useState<{ options: SelectOption[] }>({
24
+ // TODO(Zaymon): Pick colors from our limited set.
25
+ options: [
26
+ { id: 'opt_1', title: 'First option', color: 'amber' },
27
+ { id: 'opt_2', title: 'Second option', color: 'emerald' },
28
+ { id: 'opt_3', title: 'Third option', color: 'rose' },
29
+ ],
30
+ });
31
+
32
+ return (
33
+ <TestLayout>
34
+ <Form.Root
35
+ schema={schema}
36
+ values={values}
37
+ fieldMap={{ options: SelectOptionField }}
38
+ onSave={(values) => setValues(values)}
39
+ >
40
+ <Form.Viewport>
41
+ <Form.Content>
42
+ <Form.FieldSet />
43
+ <Form.Actions />
44
+ </Form.Content>
45
+ </Form.Viewport>
46
+ </Form.Root>
47
+ </TestLayout>
48
+ );
49
+ };
50
+
51
+ const meta = {
52
+ title: 'ui/react-ui-form/SelectOptionField',
53
+ component: SelectOptionField as any,
54
+ render: DefaultStory,
55
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
56
+ parameters: {
57
+ layout: 'fullscreen',
58
+ translations,
59
+ },
60
+ } satisfies Meta<typeof DefaultStory>;
61
+
62
+ export default meta;
63
+
64
+ type Story = StoryObj<typeof meta>;
65
+
66
+ export const Default: Story = {};
@@ -4,30 +4,39 @@
4
4
 
5
5
  import React, { type ChangeEvent, type KeyboardEvent, useCallback, useEffect, useRef, useState } from 'react';
6
6
 
7
- import { type SelectOption } from '@dxos/echo-schema';
7
+ import { type SelectOption } from '@dxos/echo/Format';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { type ChromaticPalette, IconButton, Input, Tag, useTranslation } from '@dxos/react-ui';
10
10
  import { List } from '@dxos/react-ui-list';
11
11
  import { HuePicker } from '@dxos/react-ui-pickers';
12
- import { hues, subtleHover } from '@dxos/react-ui-theme';
12
+ import { hues, osTranslations } from '@dxos/ui-theme';
13
13
 
14
- import { translationKey } from '../../../translations';
15
- import { InputHeader, type InputProps } from '../Input';
14
+ import { translationKey } from '#translations';
16
15
 
17
- export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue, onValueChange }: InputProps) => {
16
+ import { type FormFieldComponentProps, FormFieldLabel } from '../FormFieldComponent';
17
+
18
+ export const SelectOptionField = ({
19
+ type,
20
+ readonly,
21
+ label,
22
+ jsonPath,
23
+ getStatus,
24
+ getValue,
25
+ onValueChange,
26
+ }: FormFieldComponentProps<SelectOption[] | undefined>) => {
27
+ const { t } = useTranslation(translationKey);
28
+ const { status, error } = getStatus();
18
29
  const [selected, setSelectedId] = useState<string | null>(null);
19
30
  const [isNewOption, setIsNewOption] = useState(false);
20
31
  const inputRef = useRef<HTMLInputElement>(null);
21
- const { t } = useTranslation(translationKey);
22
- const { status, error } = getStatus();
23
- const options = getValue<SelectOption[] | undefined>();
32
+ const options = getValue();
24
33
 
25
34
  // Initialization.
26
35
  useEffect(() => {
27
36
  if (options === undefined) {
28
37
  onValueChange(type, []);
29
38
  }
30
- }, [options, onValueChange, type]);
39
+ }, [options, type, onValueChange]);
31
40
 
32
41
  const randomHue = () => {
33
42
  const usedHues = new Set(options?.map((option) => option.color) ?? []);
@@ -88,8 +97,8 @@ export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue,
88
97
  [options, type, onValueChange],
89
98
  );
90
99
 
91
- const handleKeyDown = useCallback((e: KeyboardEvent<HTMLInputElement>) => {
92
- if (e.key === 'Enter') {
100
+ const handleKeyDown = useCallback((ev: KeyboardEvent<HTMLInputElement>) => {
101
+ if (ev.key === 'Enter') {
93
102
  setSelectedId(null);
94
103
  }
95
104
  }, []);
@@ -111,14 +120,14 @@ export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue,
111
120
 
112
121
  return (
113
122
  <Input.Root validationValence={status}>
114
- <InputHeader error={error} label={label} />
115
- <div role='none'>
123
+ <FormFieldLabel error={error} readonly={readonly} label={label} path={jsonPath} />
124
+ <div>
116
125
  {options && (
117
126
  <List.Root
118
127
  items={options}
119
- isItem={(item) => true}
120
- onMove={disabled ? undefined : handleMove}
121
- readonly={disabled}
128
+ isItem={(_item) => true}
129
+ onMove={readonly ? undefined : handleMove}
130
+ readonly={!!readonly}
122
131
  >
123
132
  {({ items }) => (
124
133
  <div role='list' className='w-full overflow-auto'>
@@ -127,11 +136,11 @@ export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue,
127
136
  <List.Item
128
137
  role='button'
129
138
  item={item}
130
- classNames={[subtleHover, 'flex flex-col cursor-pointer rounded-sm']}
139
+ classNames='flex flex-col cursor-pointer rounded-xs dx-hover'
131
140
  aria-expanded={selected === item.id}
132
141
  >
133
142
  <div className='flex items-center'>
134
- <List.ItemDragHandle disabled={disabled} />
143
+ <List.ItemDragHandle disabled={!!readonly} />
135
144
  <List.ItemTitle onClick={() => handleClick(item.id)} classNames='flex-1'>
136
145
  {/* TODO(ZaymonFC): Move spacer into Tag component. */}
137
146
  <Tag palette={item.color as ChromaticPalette}>{item.title || '\u200b'}</Tag>
@@ -139,32 +148,30 @@ export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue,
139
148
  <IconButton
140
149
  iconOnly
141
150
  variant='ghost'
142
- label={t(selected === item.id ? 'collapse label' : 'expand label', { ns: 'os' })}
151
+ label={t(selected === item.id ? 'collapse.label' : 'expand.label', { ns: osTranslations })}
143
152
  icon={selected === item.id ? 'ph--caret-down--regular' : 'ph--caret-right--regular'}
144
153
  onClick={() => handleClick(item.id)}
145
154
  />
146
155
  </div>
147
156
  {selected === item.id && (
148
- <div className='pli-cardSpacingInline plb-cardSpacingBlock flex flex-col gap-1 density-fine'>
149
- {/* 16px to match drag handle width. */}
150
- <Input.Label classNames='text-xs'>{t('select option label')}</Input.Label>
151
- <div className='grid grid-cols-[1fr_min-content_min-content] gap-1'>
157
+ <div className='flex flex-col p-form-padding gap-form-gap dx-density-md'>
158
+ <Input.Label classNames='text-sm'>{t('select-option.label')}</Input.Label>
159
+ <div className='grid grid-cols-[1fr_min-content_min-content] gap-form-gap'>
152
160
  <Input.TextInput
153
- disabled={disabled}
154
- placeholder={t('select option label placeholder')}
161
+ disabled={!!readonly}
162
+ placeholder={t('select-option-label.placeholder')}
155
163
  ref={selected === item.id ? inputRef : undefined}
156
164
  value={item.title}
157
165
  onChange={handleTitleChange(item.id)}
158
166
  onKeyDown={handleKeyDown}
159
167
  classNames='flex-1'
160
- data-no-submit
161
168
  />
162
- <HuePicker disabled={disabled} value={item.color} onChange={handleColorChange(item.id)} />
169
+ <HuePicker disabled={!!readonly} value={item.color} onChange={handleColorChange(item.id)} />
163
170
  <IconButton
164
- disabled={disabled}
171
+ disabled={!!readonly}
165
172
  icon='ph--trash--fill'
166
173
  iconOnly
167
- label={t('select option delete')}
174
+ label={t('select-option-delete.button')}
168
175
  onClick={() => handleDelete(item.id)}
169
176
  />
170
177
  </div>
@@ -176,10 +183,10 @@ export const SelectOptionInput = ({ type, label, disabled, getStatus, getValue,
176
183
  <IconButton
177
184
  variant='ghost'
178
185
  icon='ph--plus--regular'
179
- label={t('select option add')}
186
+ label={t('select-option-add.button')}
180
187
  onClick={handleAdd}
181
- disabled={disabled}
182
- classNames='is-full'
188
+ disabled={!!readonly}
189
+ classNames='w-full'
183
190
  />
184
191
  </div>
185
192
  )}
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { Input, type TextAreaProps } from '@dxos/react-ui';
8
+
9
+ import { type FormFieldComponentProps, FormFieldWrapper } from '../FormFieldComponent';
10
+
11
+ export const TextAreaField = ({
12
+ type,
13
+ readonly,
14
+ placeholder,
15
+ onValueChange,
16
+ onBlur,
17
+ ...props
18
+ }: FormFieldComponentProps<string>) => {
19
+ const handleChange = useCallback<NonNullable<TextAreaProps['onChange']>>(
20
+ (event) => onValueChange(type, event.target.value),
21
+ [type, onValueChange],
22
+ );
23
+
24
+ return (
25
+ <FormFieldWrapper<string> readonly={readonly} {...props}>
26
+ {({ value = '' }) => (
27
+ <Input.TextArea
28
+ rows={5}
29
+ disabled={!!readonly}
30
+ placeholder={placeholder}
31
+ value={value}
32
+ onChange={handleChange}
33
+ onBlur={onBlur}
34
+ />
35
+ )}
36
+ </FormFieldWrapper>
37
+ );
38
+ };
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { Input, type TextInputProps } from '@dxos/react-ui';
8
+
9
+ import { type FormFieldComponentProps, FormFieldWrapper } from '../FormFieldComponent';
10
+
11
+ export const TextField = ({
12
+ type,
13
+ readonly,
14
+ placeholder,
15
+ onBlur,
16
+ onValueChange,
17
+ ...props
18
+ }: FormFieldComponentProps<string>) => {
19
+ const handleChange = useCallback<NonNullable<TextInputProps['onChange']>>(
20
+ (event) => onValueChange(type, event.target.value),
21
+ [type, onValueChange],
22
+ );
23
+
24
+ return (
25
+ <FormFieldWrapper<string> readonly={readonly} {...props}>
26
+ {({ value = '' }) => (
27
+ <Input.TextInput
28
+ noAutoFill
29
+ disabled={!!readonly}
30
+ placeholder={placeholder}
31
+ value={value}
32
+ onBlur={onBlur}
33
+ onChange={handleChange}
34
+ />
35
+ )}
36
+ </FormFieldWrapper>
37
+ );
38
+ };